blob: 8e8c818c5eda0b6ca52110171a5b2f417d28a919 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.wst.ws.internal.registry;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Hashtable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.wst.ws.internal.model.v10.registry.Registry;
import org.eclipse.wst.ws.internal.model.v10.registry.RegistryFactory;
import org.eclipse.wst.ws.internal.model.v10.registry.RegistryPackage;
import org.eclipse.wst.ws.internal.model.v10.rtindex.RTIndexPackage;
import org.eclipse.wst.ws.internal.model.v10.taxonomy.Taxonomy;
import org.eclipse.wst.ws.internal.model.v10.taxonomy.TaxonomyFactory;
import org.eclipse.wst.ws.internal.model.v10.taxonomy.TaxonomyPackage;
import org.eclipse.wst.ws.internal.plugin.WSPlugin;
/**
* RegistryService is the starting class of the Web service registry
* programming model. Call the <code>RegistryService.instance()</code>
* static method to get the singleton instance of this class.
* <p>
* RegistryService provides factory methods for getting new
* instances of <code>IRegistryManager</code> objects which,
* in turn, provide the means for registering and unregistering
* groups of <code>Registry</code> and <code>Taxonomy</code> models
* at URL addressable locations in the filesystem or elsewhere.
* <p>
* RegistryService provides utility methods to ease the creation,
* loading and saving raw instances of the <code>Registry</code>
* and <code>Taxonomy</code> models, and to simplify the process of
* composing and finding <code>Taxonomy</code> models in
* <code>Registry</code> models.
* <p>
* A typical use of <code>RegistryService</code> and its related
* classes to create and save a new family of models is:
* <blockquote>
* <code>
* RegistryService registryService = RegistryService.instance();
* MyRegistry registry = MyRegistryFactory.eINSTANCE.createMyRegistry();
* // build up your registry model here
* Taxonomy taxonomy = registryService.newTaxonomy();
* // build up your taxonomy model here
* registryService.addTaxonomy(registry,taxonomy);
* IRegistryManager registryManager = registryService.getDefaultRegistryManager();
* registryManager.saveRegistry(registry);
* </code>
* </blockquote>
* @see #instance()
* @see IRegistryManager
* @see Registry
* @see Taxonomy
* @author cbrealey
*/
public class RegistryService
{
private static RegistryService instance_;
private static final String DEFAULT_INDEX_XML_FILE = "DefaultIndex.xml";
private Hashtable registryManagers_ = new Hashtable();
private IRegistryManager defaultRegistryManager_ = null;
private GenericResourceFactory resourceFactory_ = new GenericResourceFactory();
/**
* A RegistryService cannot be directly constructed.
* Use @link #instance() to get the singleton of this class.
*/
private RegistryService ()
{
Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap().put("xml",resourceFactory_);
RegistryPackage.eINSTANCE.getClass();
TaxonomyPackage.eINSTANCE.getClass();
RTIndexPackage.eINSTANCE.getClass();
}
/**
* Returns the singleton of this class.
* @return The singleton of this class.
*/
public static RegistryService instance ()
{
if (instance_ == null)
{
instance_ = new RegistryService();
}
return instance_;
}
/**
* Creates a default <code>IRegistryManager</code> for the system.
* @return The default <code>IRegistryManager</code> for the system.
* @see IRegistryManager
*/
public IRegistryManager getDefaultRegistryManager ()
{
if (defaultRegistryManager_ == null)
{
String indexFilename = WSPlugin.getDefault().getStateLocation().append(DEFAULT_INDEX_XML_FILE).toString();
defaultRegistryManager_ = new RegistryManager(indexFilename);
}
return defaultRegistryManager_;
}
/**
* Creates a new or existing <code>IRegistryManager</code> for the given URL.
* @param url A URL to the XML document that persists
* the set of registries managed by this <code>IRegistryManager</code>.
* @return The new or existing <code>RegistryManager</code> for the given URL.
* @see IRegistryManager
*/
public IRegistryManager getRegistryManager ( URL url )
{
IRegistryManager registryManager = (IRegistryManager)registryManagers_.get(url);
if (registryManager == null)
{
registryManager = new RegistryManager(url);
registryManagers_.put(url,registryManager);
}
return registryManager;
}
/**
* Removes the <code>IRegistryManager</code> for the given URL.
* No physical resources are deleted.
* @param url A URL to the XML document that persists
* the set of registries managed by this <code>IRegistryManager</code>.
* @see IRegistryManager
*/
public void removeRegistryManager ( URL url )
{
registryManagers_.remove(url);
}
/**
* Creates and returns a new <code>Registry</code> model.
* As a general rule, this method has little actual value as
* most concrete registry models will be of types that extend
* the base Registry model, such as <code>UDDIRegistry</code>.
* For example, <code>UDDIRegistryService.newUDDIRegistry()</code>
* returns a new <code>UDDIRegistry</code>. Providers of other
* concrete types of registries may provide similar facilities.
* @return A new <code>Registry</code> model. Never returns null.
* @see Registry
* @see UDDIRegistryService#newUDDIRegistry()
*/
public Registry newRegistry ()
{
return RegistryFactory.eINSTANCE.createRegistry();
}
/**
* Loads the <code>Registry</code> model from an XML document.
* If loading the model of a registry that extends the base
* Registry interface and Schema, you must initialize the EMF
* eCore package (eg. <code>MyRegistryPackage.eINSTANCE</code>
* for your model before calling this load method.
* For UDDI Registry models, this is done automatically by
* calling <code>UDDIRegistryService.instance()</code>.
* @param url The URL to the XML document to load.
* @return The <code>Registry</code> model.
* @throws <code>CoreException</code> If the model cannot be loaded.
* @see Registry
* @see UDDIRegistryService#instance()
*/
public Registry loadRegistry ( URL url ) throws CoreException
{
Resource resource = resourceFactory_.createResource(URI.createURI("*.xml"));
try
{
resource.load(getInputStreamFor(url),null);
}
catch (IOException e)
{
throw new CoreException(new Status(IStatus.ERROR,WSPlugin.ID,0,"",e));
}
org.eclipse.wst.ws.internal.model.v10.registry.DocumentRoot document = (org.eclipse.wst.ws.internal.model.v10.registry.DocumentRoot)resource.getContents().get(0);
return document.getRegistry();
}
/**
* Saves the <code>Registry</code> model to an XML document.
* @param url The URL to the XML document to save.
* @param registry The <code>Registry</code> model to save.
* @throws <code>CoreException</code> If the model cannot be saved.
* @see Registry
*/
public void saveRegistry ( URL url, Registry registry ) throws CoreException
{
org.eclipse.wst.ws.internal.model.v10.registry.DocumentRoot document = RegistryFactory.eINSTANCE.createDocumentRoot();
document.setRegistry(registry);
Resource resource = resourceFactory_.createResource(URI.createURI("*.xml"));
resource.getContents().add(document);
try
{
resource.save(getOutputStreamFor(url),null);
}
catch (IOException e)
{
throw new CoreException(new Status(IStatus.ERROR,WSPlugin.ID,0,"",e));
}
}
/**
* Creates and returns a new <code>Taxonomy</code> model.
* @return A new <code>Taxonomy</code> model. Never returns null.
* @see Taxonomy
*/
public Taxonomy newTaxonomy ()
{
return TaxonomyFactory.eINSTANCE.createTaxonomy();
}
/**
* Loads the <code>Taxonomy</code> model from an XML document.
* @param url The URL to the XML document to load.
* @return the <code>Taxonomy</code> model.
* @throws <code>CoreException</code> If the model cannot be loaded.
* @see Taxonomy
*/
public Taxonomy loadTaxonomy ( URL url ) throws CoreException
{
Resource resource = resourceFactory_.createResource(URI.createURI("*.xml"));
try
{
resource.load(getInputStreamFor(url),null);
}
catch (IOException e)
{
throw new CoreException(new Status(IStatus.ERROR,WSPlugin.ID,0,"",e));
}
org.eclipse.wst.ws.internal.model.v10.taxonomy.DocumentRoot document = (org.eclipse.wst.ws.internal.model.v10.taxonomy.DocumentRoot)resource.getContents().get(0);
return document.getTaxonomy();
}
/**
* Saves the <code>Taxonomy</code> model to an XML document.
* @param url The URL to the XML document to save.
* @param taxonomy The <code>Taxonomy</code> model to save.
* @throws <code>CoreException</code> If the model cannot be saved.
* @see Taxonomy
*/
public void saveTaxonomy ( URL url, Taxonomy taxonomy ) throws CoreException
{
org.eclipse.wst.ws.internal.model.v10.taxonomy.DocumentRoot document = TaxonomyFactory.eINSTANCE.createDocumentRoot();
document.setTaxonomy(taxonomy);
Resource resource = resourceFactory_.createResource(URI.createURI("*.xml"));
resource.getContents().add(document);
try
{
resource.save(getOutputStreamFor(url),null);
}
catch (IOException e)
{
throw new CoreException(new Status(IStatus.ERROR,WSPlugin.ID,0,"",e));
}
}
/**
* Constructs and returns a new Registry model configured
* to reference the given <code>registry</code>.
* <p>
* The given <code>registry</code> can be either a full
* model as signified by having a non-null, non-empty
* identifier (<code>registry.getId()</code>), or a
* reference itself as signified by having a non-null,
* non-empty reference (<code>registry.getRef()</code>).
* <p>
* If the given <code>registry</code> is a full model,
* then a new <code>Registry</code> is returned such that
* <ul>
* <li><code>getRef()</code> equals <code>registry.getId()</code></li>
* <li><code>getLocation()</code> is null</li>
* <li><code>getId()</code> is null</li>
* </ul>
* <p>
* In the given <code>registry</code> is itself a reference,
* then a new <code>Registry</code> is returned such that
* <ul>
* <li><code>getRef()</code> equals <code>registry.getRef()</code></li>
* <li><code>getLocation()</code> equals <code>registry.getLocation()</code></li>
* <li><code>getId()</code> is null</li>
* </ul>
*
* @param registry The <code>Registry</code> model to clone or
* refer to depending on whether the given <code>registry</code>
* is a full model or a reference.
* @return A new <code>Registry</code>, guaranteed to be a reference.
*/
public Registry newRegistryReference ( Registry registry )
{
String id = registry.getId();
String ref = registry.getRef();
Registry registryRef = newRegistry();
if (ref == null || "".equals(ref))
{
registryRef.setRef(id);
}
else
{
registryRef.setRef(ref);
registryRef.setLocation(registry.getLocation());
}
return registryRef;
}
/**
* Constructs and returns a new Taxonomy model configured
* to reference the given <code>taxonomy</code>.
* <p>
* The given <code>taxonomy</code> can be either a full
* model as signified by having a non-null, non-empty
* identifier (<code>taxonomy.getId()</code>), or a
* reference itself as signified by having a non-null,
* non-empty reference (<code>taxonomy.getRef()</code>).
* <p>
* If the given <code>taxonomy</code> is a full model,
* then a new <code>Taxonomy</code> is returned such that
* <ul>
* <li><code>getRef()</code> equals <code>taxonomy.getId()</code></li>
* <li><code>getLocation()</code> is null</li>
* <li><code>getId()</code> is null</li>
* </ul>
* <p>
* In the given <code>taxonomy</code> is itself a reference,
* then a new <code>Taxonomy</code> is returned such that
* <ul>
* <li><code>getRef()</code> equals <code>taxonomy.getRef()</code></li>
* <li><code>getLocation()</code> equals <code>taxonomy.getLocation()</code></li>
* <li><code>getId()</code> is null</li>
* </ul>
*
* @param taxonomy The <code>Taxonomy</code> model to clone or
* refer to depending on whether the given <code>taxonomy</code>
* is a full model or a reference.
* @return A new <code>Taxonomy</code>, guaranteed to be a reference.
*/
public Taxonomy newTaxonomyReference ( Taxonomy taxonomy )
{
String id = taxonomy.getId();
String ref = taxonomy.getRef();
Taxonomy taxonomyRef = newTaxonomy();
if (ref == null || "".equals(ref))
{
taxonomyRef.setRef(id);
}
else
{
taxonomyRef.setRef(ref);
taxonomyRef.setLocation(taxonomy.getLocation());
}
return taxonomyRef;
}
/**
* Returns true if and only if the given URL identifies
* a resource that exists and is a file.
* @param url The URL of the resource to check for existence.
* @return True if the URL resource exists and is a file,
* or false otherwise.
*/
static boolean exists ( URL url )
{
if ("platform".equals(url.getProtocol()))
{
String urlFile = url.getFile().trim();
IPath path = new Path(urlFile).removeFirstSegments(1);
if (path.segmentCount() <= 1)
{
return false;
}
IPath osPath = ResourcesPlugin.getWorkspace().getRoot().getFile(path).getLocation();
if (osPath == null)
{
return false;
}
File file = new File(osPath.toString());
return (file.exists() && !file.isDirectory());
}
else if ("file".equals(url.getProtocol()))
{
File file = new File(url.getFile().trim());
return (file.exists() && !file.isDirectory());
}
return false;
}
/**
* Opens an <code>OutputStream</code> for writing to
* the given <code>url</code>.
* @param url The URL of the resource to write.
* @return An OuptutStream to write to.
* @throws IOException If the stream could not be opened.
*/
static OutputStream getOutputStreamFor ( URL url ) throws IOException
{
OutputStream outputStream = null;
if ("platform".equals(url.getProtocol()))
{
String urlFile = url.getFile().trim();
IPath path = new Path(urlFile).removeFirstSegments(1);
if (path.segmentCount() <= 1)
{
throw new IOException("The Platform URL {0} is not bound to a local, writable file.");
}
IPath osPath = ResourcesPlugin.getWorkspace().getRoot().getFile(path).getLocation();
if (osPath == null)
{
throw new IOException("The Platform URL {0} is not bound to a local, writable file.");
}
File file = new File(osPath.toString());
if (file.isDirectory())
{
throw new IOException("The Platform URL {0} is bound to a folder.");
}
outputStream = new FileOutputStream(file);
}
else if ("file".equals(url.getProtocol()))
{
File file = new File(url.getFile().trim());
if (file.isDirectory())
{
throw new IOException("The File URL {0} is bound to a directory.");
}
outputStream = new FileOutputStream(file);
}
else
{
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
outputStream = connection.getOutputStream();
}
return outputStream;
}
/**
* Opens an <code>InputStream</code> for reading from
* the given <code>url</code>.
* @param url The URL of the resource to read.
* @return An InputStream to read from.
* @throws IOException If the stream could not be opened.
*/
static InputStream getInputStreamFor ( URL url ) throws IOException
{
return url.openStream();
}
}