/*
* Copyright (C) 2014 eXo Platform SAS.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.exoplatform.services.jcr.storage.value;
import org.exoplatform.container.ExoContainer;
import org.exoplatform.container.ExoContainerContext;
import org.exoplatform.services.jcr.RepositoryService;
import org.exoplatform.services.jcr.core.ManageableRepository;
import org.exoplatform.services.jcr.core.WorkspaceContainerFacade;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;
import java.net.URLStreamHandler;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* This implementation of an {@link URLConnection} allows to get a content from
* a value storage
*
* <p>The syntax of an value storage URL is:
*
* <pre>
* vs:/{repository}/{workspace}/{value-storage-id}/{resource-id}
* </pre>
*
* @author <a href="mailto:nfilotto@exoplatform.com">Nicolas Filotto</a>
* @version $Id$
*
*/
public class ValueStorageURLStreamHandler extends URLStreamHandler
{
/**
* The syntax of the expected path
*/
private static Pattern PATH_SYNTAX = Pattern.compile("/([^/]+)/([^/]+)/([^/]+)/(.*)");
/**
* The protocol to access to a value storage
*/
public static final String PROTOCOL = "vs";
/**
* A reusable instance of {@link ValueStorageURLStreamHandler}
*/
public static final ValueStorageURLStreamHandler INSTANCE = new ValueStorageURLStreamHandler();
/**
* @see java.net.URLStreamHandler#openConnection(java.net.URL)
*/
@Override
protected URLConnection openConnection(URL u) throws IOException
{
if (!u.getProtocol().equals(PROTOCOL))
throw new MalformedURLException("Only the protocol " + PROTOCOL + " is supported");
if (u.getHost() != null)
throw new MalformedURLException("The host will be automatically defined, so it is not expected");
String file = u.getFile();
Matcher m = PATH_SYNTAX.matcher(file);
if (!m.matches())
throw new MalformedURLException("The syntax of the path of the value storage URL doesn't match with"
+ " the expected syntax which is '/{repository}/{workspace}/{value-storage-id}/{resource-id}'");
ValueStorageURLConnection connection = createURLConnection(u, m.group(1), m.group(2), m.group(3));
connection.setIdResource(m.group(4));
return connection;
}
/**
* <p>Creates a new instance of {@link ValueStorageURLConnection} from the
* value storage that belongs to the provided <code>repository</code> and <code>workspace</code>
* and whose id is the provided <code>valueStorageId</code>.</p>
* <p><b>NB:</b> <i>For performance reason, this method should be overridden by
* sub classes. Indeed the default implementation will get {@link ValueStoragePluginProvider}
* from the current context but in practice, sub classes should already have it.
* The default implementation only makes sense, when it will be called directly by
* {@link ValueStorageURLStreamHandler#openConnection(URL)} which happens when
* we try to read the content of the target resource outside the context of the
* value storage.</i>
* </p>
* @param u the {@link URL} of the resource
* @param repository the name of the repository that owns the value storage
* @param workspace the name of the workspace that owns the value storage
* @param valueStorageId the id of the value storage
* @return the {@link ValueStorageURLConnection} corresponding to the resource
* @throws IOException if the {@link ValueStorageURLConnection} could not be created
*/
protected ValueStorageURLConnection createURLConnection(URL u, String repository, String workspace,
String valueStorageId) throws IOException
{
ExoContainer container = ExoContainerContext.getCurrentContainer();
RepositoryService repositoryService =
(RepositoryService)container.getComponentInstanceOfType(RepositoryService.class);
if (repositoryService == null)
throw new IOException("Could not find the repository service");
try
{
ManageableRepository repo = repositoryService.getRepository(repository);
WorkspaceContainerFacade workspaceContainer = repo.getWorkspaceContainer(workspace);
ValueStoragePluginProvider provider =
(ValueStoragePluginProvider)workspaceContainer.getComponent(ValueStoragePluginProvider.class);
if (provider == null)
throw new IOException("Could not find the ValueStoragePluginProvider for " + repository + "/" + workspace);
return provider.createURLConnection(valueStorageId, u);
}
catch (IOException e)
{
throw e;
}
catch (Exception e)
{
throw new IOException("Could not get ValueStorageURLConnection from the value storage " + repository + "/"
+ workspace + "/" + valueStorageId, e);
}
}
/**
* @see java.net.URLStreamHandler#parseURL(java.net.URL, java.lang.String, int, int)
*/
@Override
protected void parseURL(URL u, String spec, int start, int limit)
{
setURL(u, PROTOCOL, null, -1, null, null, spec.substring(start, limit), null, null);
}
}