--- /dev/null
+/**
+ *
+ */
+package jalview.ws.dbsources.das.datamodel;
+
+import java.net.HttpURLConnection;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.StringTokenizer;
+import java.util.Vector;
+
+import javax.swing.JOptionPane;
+
+import org.apache.http.auth.InvalidCredentialsException;
+import org.biodas.jdas.client.ConnectionPropertyProviderI;
+import org.biodas.jdas.client.SourcesClient;
+import org.biodas.jdas.dassources.Capabilities;
+import org.biodas.jdas.schema.sources.CAPABILITY;
+import org.biodas.jdas.schema.sources.SOURCE;
+import org.biodas.jdas.schema.sources.SOURCES;
+import org.biodas.jdas.schema.sources.VERSION;
+
+import jalview.bin.Cache;
+import jalview.ws.dbsources.das.api.DasSourceRegistryI;
+import jalview.ws.dbsources.das.api.jalviewSourceI;
+
+/**
+ *
+ */
+public class DasSourceRegistry implements DasSourceRegistryI
+{
+ // private org.biodas.jdas.schema.sources.SOURCE[] dasSources = null;
+ private List<jalviewSourceI> dasSources = null;
+
+ private Hashtable<String, jalviewSourceI> sourceNames = null;
+
+ private Hashtable<String, jalviewSourceI> localSources = null;
+
+ public static String DEFAULT_REGISTRY = "http://www.dasregistry.org/das1/sources/";
+
+ /**
+ * true if thread is running and we are talking to DAS registry service
+ */
+ private boolean loadingDasSources = false;
+
+ public boolean isLoadingDasSources()
+ {
+ return loadingDasSources;
+ }
+
+ public String getDasRegistryURL()
+ {
+ String registry = jalview.bin.Cache.getDefault("DAS_REGISTRY_URL",
+ DEFAULT_REGISTRY);
+
+ if (registry.indexOf("/registry/das1/sources/") > -1)
+ {
+ jalview.bin.Cache.setProperty(jalview.bin.Cache.DAS_REGISTRY_URL,
+ DEFAULT_REGISTRY);
+ registry = DEFAULT_REGISTRY;
+ }
+ return registry;
+ }
+
+ /**
+ * query the default DAS Source Registry for sources. Uses value of jalview
+ * property DAS_REGISTRY_URL and the DasSourceBrowser.DEFAULT_REGISTRY if that
+ * doesn't exist.
+ *
+ * @return list of sources
+ */
+ private List<jalviewSourceI> getDASSources()
+ {
+
+ return getDASSources(getDasRegistryURL());
+ }
+
+ /**
+ * query the given URL for DasSources.
+ *
+ * @param registryURL
+ * return sources from registryURL
+ */
+ private static List<jalviewSourceI> getDASSources(String registryURL)
+ {
+ try
+ {
+ URL url = new URL(registryURL);
+ org.biodas.jdas.client.SourcesClientInterface client = new SourcesClient();
+
+ SOURCES sources = client.fetchDataRegistry(registryURL, null, null, null, null, null, null);
+
+ List<SOURCE> dassources = sources.getSOURCE();
+ ArrayList<jalviewSourceI> dsrc = new ArrayList<jalviewSourceI>();
+ for (SOURCE src : dassources)
+ {
+ dsrc.add(new JalviewSource(src, false));
+ }
+ return dsrc;
+ } catch (Exception ex)
+ {
+ System.err.println("Failed to contact DAS1 registry at "
+ + registryURL);
+ ex.printStackTrace();
+ return new ArrayList<jalviewSourceI>();
+ }
+ }
+
+
+ public void run()
+ {
+ getSources();
+ }
+
+ @Override
+ public List<jalviewSourceI> getSources()
+ {
+ if (dasSources == null)
+ {
+ dasSources = getDASSources();
+ }
+ return appendLocalSources();
+ }
+
+ /**
+ * generate Sources from the local das source list
+ *
+ */
+ private void addLocalDasSources()
+ {
+ String local = jalview.bin.Cache.getProperty("DAS_LOCAL_SOURCE");
+ if (local != null)
+ {
+ StringTokenizer st = new StringTokenizer(local, "\t");
+ while (st.hasMoreTokens())
+ {
+ String token = st.nextToken();
+ int bar = token.indexOf("|");
+ String url = token.substring(bar + 1);
+ boolean features = true, sequence = false;
+ if (url.startsWith("sequence:"))
+ {
+ url = url.substring(9);
+ // this source also serves sequences as well as features
+ sequence = true;
+ }
+ createLocalSource(url, token.substring(0, bar), sequence, features);
+ }
+ }
+ }
+
+ private List<jalviewSourceI> appendLocalSources()
+ {
+ List<jalviewSourceI> srclist=new ArrayList<jalviewSourceI>();
+ addLocalDasSources();
+ sourceNames = new Hashtable<String, jalviewSourceI>();
+ if (dasSources != null)
+ {
+ for (jalviewSourceI src : dasSources)
+ {
+ sourceNames.put(src.getTitle(), src);
+ srclist.add(src);
+ }
+ }
+
+ if (localSources == null)
+ {
+ return srclist;
+ }
+ Enumeration en = localSources.keys();
+ while (en.hasMoreElements())
+ {
+ String key = en.nextElement().toString();
+ jalviewSourceI jvsrc = localSources.get(key);
+ sourceNames.put(key, jvsrc);
+ srclist.add(jvsrc);
+ }
+ return srclist;
+ }
+
+ /*
+ *
+ */
+
+ @Override
+ public jalviewSourceI createLocalSource(String url, String name,
+ boolean sequence, boolean features)
+ {
+ SOURCE local = _createLocalSource(url, name, sequence, features);
+
+ if (localSources == null)
+ {
+ localSources = new Hashtable<String, jalviewSourceI>();
+ }
+ jalviewSourceI src=new JalviewSource(local, true);
+ localSources.put(local.getTitle(), src);
+ return src;
+ }
+
+ private SOURCE _createLocalSource(String url, String name,
+ boolean sequence, boolean features)
+ {
+ SOURCE local = new SOURCE();
+
+ local.setUri(url);
+ local.setTitle(name);
+ local.setVERSION(new ArrayList<VERSION>());
+ VERSION v = new VERSION();
+ List<CAPABILITY> cp = new ArrayList<CAPABILITY>();
+ if (sequence)
+ {
+ /*
+ * Could try and synthesize a coordinate system for the source if needbe
+ * COORDINATES coord = new COORDINATES(); coord.setAuthority("NCBI");
+ * coord.setSource("Chromosome"); coord.setTaxid("9606");
+ * coord.setVersion("35"); version.getCOORDINATES().add(coord);
+ */
+ CAPABILITY cap = new CAPABILITY();
+ cap.setType("das1:" + Capabilities.SEQUENCE.getName());
+ cap.setQueryUri(url+"/sequence");
+ cp.add(cap);
+ }
+ if (features)
+ {
+ CAPABILITY cap = new CAPABILITY();
+ cap.setType("das1:" + Capabilities.FEATURES.getName());
+ cap.setQueryUri(url+"/features");
+ cp.add(cap);
+ }
+
+ v.getCAPABILITY().addAll(cp);
+ local.getVERSION().add(v);
+
+ return local;
+ }
+
+ @Override
+ public jalviewSourceI getSource(String nickname)
+ {
+ return sourceNames.get(nickname);
+ }
+
+ @Override
+ public boolean removeLocalSource(jalviewSourceI source)
+ {
+ if (localSources.containsValue(source))
+ {
+ localSources.remove(source.getTitle());
+ sourceNames.remove(source.getTitle());
+ dasSources.remove(source);
+ return true;
+ }
+ return false;
+ }
+
+ @Override
+ public void refreshSources()
+ {
+ dasSources = null;
+ sourceNames = null;
+ run();
+ }
+
+ @Override
+ public List<jalviewSourceI> resolveSourceNicknames(List<String> sources)
+ {
+ ArrayList<jalviewSourceI> resolved = new ArrayList<jalviewSourceI>();
+ if (sourceNames != null)
+ {
+ for (String src : sources)
+ {
+ jalviewSourceI dsrc = sourceNames.get(src);
+ if (dsrc != null)
+ {
+ resolved.add(dsrc);
+ }
+ }
+ }
+ return resolved;
+ }
+
+ @Override
+ public String getLocalSourceString()
+ {
+ if (localSources != null)
+ {
+ StringBuffer sb = new StringBuffer();
+ Enumeration en = localSources.keys();
+ while (en.hasMoreElements())
+ {
+ String token = en.nextElement().toString();
+ jalviewSourceI srco = localSources.get(token);
+ sb.append(token + "|"
+ + (srco.isSequenceSource() ? "sequence:" : "")
+ + srco.getUri() + "\t");
+ }
+ return sb.toString();
+ }
+ return "";
+ }
+
+ private static final Hashtable<URL, String> authStash;
+ static
+ {
+ authStash = new Hashtable<URL, String>();
+
+ try
+ {
+ // TODO: allow same credentials for https and http
+ authStash.put(new URL(
+ "http://www.compbio.dundee.ac.uk/geneweb/das/myseq/"),
+ "Basic SmltOm1pSg==");
+ } catch (MalformedURLException e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ public Map<String, ConnectionPropertyProviderI> getSessionHandler()
+ {
+ final ConnectionPropertyProviderI conprov = new ConnectionPropertyProviderI()
+ {
+ boolean authed = false;
+
+ @Override
+ public void setConnectionProperties(HttpURLConnection connection)
+ {
+ String auth = authStash.get(connection.getURL());
+ if (auth != null && auth.length() > 0)
+ {
+ connection.setRequestProperty("Authorisation", auth);
+ authed = true;
+ }
+ else
+ {
+ authed = false;
+ }
+ }
+
+ @Override
+ public boolean getResponseProperties(HttpURLConnection connection)
+ {
+ String auth = authStash.get(connection.getURL());
+ if (auth != null && auth.length() == 0)
+ {
+ // don't attempt to check if we authed or not - user entered empty
+ // password
+ return false;
+ }
+ if (!authed)
+ {
+ if (auth != null)
+ {
+ // try and pass credentials.
+ return true;
+ }
+ // see if we should try and create a new auth record.
+ String ameth = connection.getHeaderField("X-DAS-AuthMethods");
+ Cache.log.debug("Could authenticate to " + connection.getURL()
+ + " with : " + ameth);
+ // TODO: search auth string and raise login box - return if auth was
+ // provided
+ return false;
+ }
+ else
+ {
+ // check to see if auth was successful
+ String asuc = connection
+ .getHeaderField("X-DAS_AuthenticatedUser");
+ if (asuc != null && asuc.trim().length() > 0)
+ {
+ // authentication was successful
+ Cache.log.debug("Authenticated successfully as " + asuc
+ + " with " + connection.getURL().toString());
+ return false;
+ }
+ // it wasn't - so we should tell the user it failed and ask if they
+ // want to attempt authentication again.
+ authStash.remove(connection.getURL());
+ // open a new login/password dialog with cancel button
+ // set new authStash content with password and return true
+ return true; //
+ // User cancelled auth - so put empty string in stash to indicate we
+ // don't want to auth with this server.
+ // authStash.put(connection.getURL(), "");
+ // return false;
+ }
+ }
+ };
+ return new Map<String, ConnectionPropertyProviderI>()
+ {
+
+ @Override
+ public void clear()
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean containsKey(Object key)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean containsValue(Object value)
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Set<java.util.Map.Entry<String, ConnectionPropertyProviderI>> entrySet()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ConnectionPropertyProviderI get(Object key)
+ {
+ return conprov;
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public Set<String> keySet()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public ConnectionPropertyProviderI put(String key,
+ ConnectionPropertyProviderI value)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public void putAll(
+ Map<? extends String, ? extends ConnectionPropertyProviderI> m)
+ {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public ConnectionPropertyProviderI remove(Object key)
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ @Override
+ public int size()
+ {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public Collection<ConnectionPropertyProviderI> values()
+ {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ };
+ }
+
+}
--- /dev/null
+package jalview.ws.dbsources.das.datamodel;
+
+import java.text.ParseException;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.biodas.jdas.dassources.Capabilities;
+import org.biodas.jdas.dassources.utils.DasTimeFormat;
+import org.biodas.jdas.dassources.utils.RegistrySourceAdapter;
+import org.biodas.jdas.schema.sources.CAPABILITY;
+import org.biodas.jdas.schema.sources.COORDINATES;
+import org.biodas.jdas.schema.sources.MAINTAINER;
+import org.biodas.jdas.schema.sources.PROP;
+import org.biodas.jdas.schema.sources.SOURCE;
+import org.biodas.jdas.schema.sources.VERSION;
+
+import sun.plugin2.message.GetNameSpaceMessage;
+
+import jalview.ws.dbsources.DasSequenceSource;
+import jalview.ws.dbsources.das.api.jalviewSourceI;
+import jalview.ws.seqfetcher.DbSourceProxy;
+
+public class JalviewSource implements jalviewSourceI
+{
+ SOURCE source;
+
+ public JalviewSource(SOURCE local2, boolean local)
+ {
+ this.local = local;
+ source = local2;
+ }
+
+ @Override
+ public String getTitle()
+ {
+ return source.getTitle();
+ }
+
+ @Override
+ public VERSION getVersion()
+ {
+
+ return getVersionFor(source);
+ }
+
+ @Override
+ public String getDocHref()
+ {
+ return source.getDocHref();
+ }
+
+ @Override
+ public String getDescription()
+ {
+ return source.getDescription();
+ }
+
+ @Override
+ public String getUri()
+ {
+ return source.getUri();
+ }
+
+ @Override
+ public MAINTAINER getMAINTAINER()
+ {
+ return source.getMAINTAINER();
+ }
+
+ @Override
+ public String getEmail()
+ {
+ return (local) ? null: source.getMAINTAINER().getEmail();
+ }
+
+ boolean local = false;
+
+ @Override
+ public boolean isLocal()
+ {
+ return local;
+ }
+
+ @Override
+ public boolean isSequenceSource()
+ {
+ String seqcap = "das1:" + Capabilities.SEQUENCE.getName();
+ for (String cp : getCapabilityList(getVersionFor(source)))
+ {
+ if (cp.equals(seqcap))
+ {
+ return true;
+
+ }
+ }
+ return false;
+ }
+ @Override
+ public boolean isFeatureSource()
+ {
+ String seqcap = "das1:" + Capabilities.FEATURES.getName();
+ for (String cp : getCapabilityList(getVersionFor(source)))
+ {
+ if (cp.equals(seqcap))
+ {
+ return true;
+
+ }
+ }
+ return false;
+ }
+
+ private VERSION getVersionFor(SOURCE ds)
+ {
+ VERSION latest = null;
+ for (VERSION v : ds.getVERSION())
+ {
+ if (latest == null
+ || isLaterThan(latest.getCreated(), v.getCreated()))
+ {
+ // TODO: das 1.6 - should just get the first version - ignore other
+ // versions since not specified how to construct URL from version's URI
+ // + source URI
+ latest = v;
+ }
+ }
+ return latest;
+ }
+
+ private boolean isLaterThan(String ref, String newer)
+ {
+ Date refdate = null, newdate = null;
+ try
+ {
+ refdate = DasTimeFormat.fromDASString(ref);
+
+ } catch (ParseException x)
+ {
+ return false;
+ }
+ try
+ {
+ newdate = DasTimeFormat.fromDASString(newer);
+ } catch (ParseException e)
+ {
+ // TODO: handle exception
+ }
+ if (refdate != null)
+ {
+ if (newdate != null)
+ {
+ return refdate.before(newdate);
+ }
+ return false;
+ }
+ if (newdate != null)
+ {
+ return true;
+ }
+ // assume first instance of source is newest in list. - TODO: check if
+ // natural ordering of source versions is newest first or oldest first
+ return false;
+ }
+
+ public String[] getLabelsFor(VERSION v)
+ {
+ ArrayList<String> labels = new ArrayList<String>();
+ for (PROP p : v.getPROP())
+ {
+ if (p.getName().equalsIgnoreCase("LABEL"))
+ {
+ labels.add(p.getValue());
+ }
+ }
+ return labels.toArray(new String[0]);
+ }
+
+ private CAPABILITY getCapability(Capabilities capability) {
+ for (CAPABILITY p: getVersion().getCAPABILITY()) {
+ if (p.getType().equalsIgnoreCase(capability.getName()) || p.getType().equalsIgnoreCase("das1:"+capability.getName()))
+ {
+ return p;
+ }
+ }
+ return null;
+ }
+ public String[] getCapabilityList(VERSION v)
+ {
+
+ ArrayList<String> labels = new ArrayList<String>();
+ for (CAPABILITY p : v.getCAPABILITY())
+ {
+ // TODO: work out what to do with namespace prefix
+ // does SEQUENCE == das1:SEQUENCE and das2:SEQUENCE ?
+ // for moment, just show all capabilities...
+ if (p.getType().startsWith("das1:"))
+ {
+ labels.add(p.getType());
+ }
+ }
+ return labels.toArray(new String[0]);
+ }
+
+ @Override
+ public List<DbSourceProxy> getSequenceSourceProxies()
+ {
+ if (!isSequenceSource())
+ {
+ return null;
+ }
+ ArrayList<DbSourceProxy> seqsources = new ArrayList<DbSourceProxy>();
+ if (!local)
+ {
+ VERSION v = getVersion();
+ for (COORDINATES cs : v.getCOORDINATES())
+ {
+
+ /*
+ * if (css == null || css.length == 0) { // TODO: query das source
+ * directly to identify coordinate system... or // have to make up a
+ * coordinate system css = new DasCoordinateSystem[] { new
+ * DasCoordinateSystem() }; css[0].setName(d1s.getNickname());
+ * css[0].setUniqueId(d1s.getNickname()); } for (int c = 0; c <
+ * css.length; c++) {
+ */
+ try
+ {
+ seqsources.add(new DasSequenceSource("das:" + getTitle() + " ("
+ + cs.getContent() + ")", cs.getContent(), source, v, cs));
+ } catch (Exception e)
+ {
+ System.err.println("Ignoring sequence coord system " + cs + " ("
+ + cs.getContent() + ") for source " + getTitle()
+ + "- threw exception when constructing fetcher.\n");
+ e.printStackTrace();
+ }
+ }
+ } else {
+ try
+ {
+ seqsources.add(new DasSequenceSource("das:"+getTitle(), getTitle(), source, getVersion(), null));
+ } catch (Exception e)
+ {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+ return seqsources;
+ }
+ @Override
+ public String getSourceURL()
+ {
+ try {
+ String url = new RegistrySourceAdapter(source).getOriginalDataSourceUri();
+ return url;
+ }
+ catch (Exception x)
+ {
+ System.err.println("Serious: Couldn't get the URL for source "+source.getTitle());
+ x.printStackTrace();
+ }
+ return null;
+ }
+}