/* * Copyright (C) 2009 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.ext.resource; import org.exoplatform.commons.utils.ClassLoading; import org.exoplatform.commons.utils.PrivilegedSystemHelper; import org.exoplatform.services.jcr.datamodel.Identifier; import org.exoplatform.services.log.ExoLogger; import org.exoplatform.services.log.Log; import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; import java.net.URL; import java.net.URLStreamHandler; import java.util.StringTokenizer; /** * Created by The eXo Platform SAS . * * @author Gennady Azarenkov * @version $Id: $ */ public class UnifiedNodeReference { private static final Log LOG = ExoLogger.getLogger("org.exoplatform.services.jcr.ext.resource.UnifiedNodeReference"); public static final String JCR_SCHEME = "jcr"; private String userInfo; private String repository; private String workspace; private Identifier id; private String path; private static URLStreamHandler handler; public UnifiedNodeReference(final String spec) throws URISyntaxException, MalformedURLException { this(new URL(null, spec, getURLStreamHandler())); } public UnifiedNodeReference(final URL url) throws URISyntaxException { this(url.toURI()); } public UnifiedNodeReference(final URI uri) throws URISyntaxException { String scheme = uri.getScheme(); if (uri.getScheme() == null) scheme = JCR_SCHEME; if (!scheme.equals(JCR_SCHEME)) throw new URISyntaxException(scheme, "Only 'jcr' scheme is acceptable!"); userInfo = uri.getUserInfo(); repository = uri.getHost(); workspace = parseWorkpace(uri); String fragment = uri.getFragment(); if (fragment != null) { if (fragment.startsWith("/")) this.path = fragment; else this.id = new Identifier(uri.getFragment()); } else throw new URISyntaxException(fragment, "Neither Path nor Identifier defined!"); } public UnifiedNodeReference(final URI uri, final String defaultRepository, final String defaultWorkspace) throws URISyntaxException { String scheme = uri.getScheme(); if (uri.getScheme() == null) scheme = JCR_SCHEME; if (!scheme.equals(JCR_SCHEME)) throw new URISyntaxException(scheme, "Only 'jcr' scheme is acceptable!"); userInfo = uri.getUserInfo(); repository = uri.getHost(); if (repository == null) repository = defaultRepository; workspace = parseWorkpace(uri); if (workspace == null || workspace.length() == 0) workspace = defaultWorkspace; String fragment = uri.getFragment(); if (fragment != null) { if (fragment.startsWith("/")) this.path = fragment; else this.id = new Identifier(uri.getFragment()); } else throw new URISyntaxException(fragment, "Neither Path nor Identifier defined!"); } public UnifiedNodeReference(final String repository, final String workspace, final Identifier identifier) { this.repository = repository; this.workspace = workspace; this.id = identifier; } public UnifiedNodeReference(final String repository, final String workspace, final String path) { this.repository = repository; this.workspace = workspace; this.path = path; } /** * @return the repository name. */ public String getRepository() { return repository; } /** * @return the workspace name. */ public String getWorkspace() { return workspace; } /** * @return the node identifier. */ public Identifier getIdentitifier() { return id; } /** * @return true if UUID used as node identifier. */ public boolean isIdentitifier() { return id != null; } /** * @return the node path. */ public String getPath() { return path; } /** * @return true if full path used as node identifier. */ public boolean isPath() { return path != null; } /** * @return the user info part of URL, it looks like <code>user:pass</code>. */ public String getUserInfo() { return userInfo; } /** * @return the URI of node. * @throws URISyntaxException */ public URI getURI() throws URISyntaxException { if (id != null) return new URI(JCR_SCHEME, userInfo, repository, -1, '/' + workspace, null, id.getString()); else if (path != null) return new URI(JCR_SCHEME, userInfo, repository, -1, '/' + workspace, null, path); throw new URISyntaxException("", "Path or Idenfifier is not defined!"); } /** * @return the URL of node. * @throws MalformedURLException */ public URL getURL() throws MalformedURLException { URI uri; try { uri = getURI(); } catch (URISyntaxException e) { throw new MalformedURLException(); } try { return new URL(uri.toString()); } catch (MalformedURLException e) { // If handler can't be found by java.net.URL#getStreamHandler() return new URL(null, uri.toString(), getURLStreamHandler()); } } /** * @return the handler for protocol <code>jcr</code>. * * @see java.net.URLStreamHandler */ public static URLStreamHandler getURLStreamHandler() { if (handler != null) return handler; // use Class#forName(), instead created by 'new' to be sure handler // was started and set required system property. // Usually this job must be done by java.net.URL, but it does // not work in web container. Under tomcat class of handler can't be found in // $CATALINA_HOME/lib/*.jar. Probably the same problem can be under AS. String packagePrefixList = PrivilegedSystemHelper.getProperty("java.protocol.handler.pkgs"); if (packagePrefixList == null) return null; StringTokenizer packagePrefixIter = new StringTokenizer(packagePrefixList, "|"); while (handler == null && packagePrefixIter.hasMoreTokens()) { String packagePrefix = packagePrefixIter.nextToken().trim(); try { String clsName = packagePrefix + "." + JCR_SCHEME + ".Handler"; Class<?> cls = ClassLoading.forName(clsName, UnifiedNodeReference.class); if (cls != null) { handler = (URLStreamHandler)cls.newInstance(); } } catch (ExceptionInInitializerError e) { // exceptions can get thrown here if class not be loaded y system ClassLoader // or if class can't be instantiated. if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + e.getMessage()); } } catch (SecurityException e) { // exceptions can get thrown here if class not be loaded y system ClassLoader // or if class can't be instantiated. if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + e.getMessage()); } } catch (ClassNotFoundException e) { // exceptions can get thrown here if class not be loaded y system ClassLoader // or if class can't be instantiated. if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + e.getMessage()); } } catch (InstantiationException e) { // exceptions can get thrown here if class not be loaded y system ClassLoader // or if class can't be instantiated. if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + e.getMessage()); } } catch (IllegalAccessException e) { // exceptions can get thrown here if class not be loaded y system ClassLoader // or if class can't be instantiated. if (LOG.isTraceEnabled()) { LOG.trace("An exception occurred: " + e.getMessage()); } } } return handler; } private static String parseWorkpace(URI uri) { String path = uri.getPath(); int sl = path.indexOf('/', 1); if (sl <= 0) return path.substring(1); return path.substring(1, sl); } }