All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.jackrabbit.net.JCRJarURLHandler Maven / Gradle / Ivy

/*
 * 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.apache.jackrabbit.net;

import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLConnection;

import javax.jcr.Session;

/**
 * The JCRJarURLHandler is the URLStreamHandler for
 * Java Archive URLs for archives from a JCR Repository URLs (JCRJar URL). The
 * scheme for such ULRs will be jar while the file part of the URL
 * has the scheme jcr.
 * 

* JCRJar URLs have not been standardized yet and may only be created in the * context of an existing Session. Therefore this handler is not * globally available and JCR Repository URLs may only be created through the * factory methods in the {@link org.apache.jackrabbit.net.URLFactory} class. *

* This class is not intended to be subclassed or instantiated by clients. * * @author Felix Meschberger * * @see org.apache.jackrabbit.net.JCRJarURLConnection * @see org.apache.jackrabbit.net.URLFactory * @see org.apache.jackrabbit.net.URLFactory#createJarURL(Session, String, String) */ class JCRJarURLHandler extends JCRURLHandler { /** * Creates an instance of this handler class. * * @param session The Session supporting this handler. This * must not be null. * * @throws NullPointerException if session is null. */ JCRJarURLHandler(Session session) { super(session); } //---------- URLStreamHandler abstracts ------------------------------------ /** * Gets a connection object to connect to an JCRJar URL. * * @param url The JCRJar URL to connect to. * * @return An instance of the {@link JCRJarURLConnection} class. * * @see JCRJarURLConnection */ protected URLConnection openConnection(URL url) { return new JCRJarURLConnection(url, this); } /** * Parses the string representation of a URL into a * URL object. *

* If there is any inherited context, then it has already been copied into * the URL argument. *

* The parseURL method of URLStreamHandler * parses the string representation as if it were an http * specification. Most URL protocol families have a similar parsing. A * stream protocol handler for a protocol that has a different syntax must * override this routine. * * @param url the URL to receive the result of parsing the * spec. * @param spec the String representing the URL that must be * parsed. * @param start the character index at which to begin parsing. This is just * past the ':' (if there is one) that specifies * the determination of the protocol name. * @param limit the character position to stop parsing at. This is the end * of the string or the position of the "#" * character, if present. All information after the sharp sign * indicates an anchor. */ protected void parseURL(URL url, String spec, int start, int limit) { // protected void parseURL(URL url, String s, int i, int j) String file = null; String ref = null; // split the reference and file part int hash = spec.indexOf('#', limit); boolean emptyFile = hash == start; if (hash > -1) { ref = spec.substring(hash + 1, spec.length()); if (emptyFile) { file = url.getFile(); } } boolean isSpecAbsolute = spec.substring(0, 4).equalsIgnoreCase("jar:"); spec = spec.substring(start, limit); if (isSpecAbsolute) { // get the file part from the absolute spec file = parseAbsoluteSpec(spec); } else if (!emptyFile) { // build the file part from the url and relative spec file = parseContextSpec(url, spec); // split archive and entry names int bangSlash = indexOfBangSlash(file); String archive = file.substring(0, bangSlash); String entry = file.substring(bangSlash); // collapse /../, /./ and // entry = canonizeString(entry); file = archive + entry; } setURL(url, "jar", "", -1, null, null, file, null, ref); } //---------- internal ----------------------------------------------------- /** * Finds the position of the bang slash (!/) in the file part of the URL. */ static int indexOfBangSlash(String file) { for (int i = file.length(); (i = file.lastIndexOf('!', i)) != -1; i--) { if (i != file.length() - 1 && file.charAt(i + 1) == '/') { return i + 1; } } return -1; } /** * Parses the URL spec and checks whether it contains a bang slash and * whether it would get a valid URL. Returns the same value if everything is * fine else a NullPointerException is thrown. * * @param spec The URL specification to check. * @return The spec if everything is ok. * @throws NullPointerException if either no bang slash is contained in the * spec or if the spec without the bang slash part would not be * a valid URL. */ private String parseAbsoluteSpec(String spec) { // find and check bang slash int bangSlash = indexOfBangSlash(spec); if (bangSlash == -1) { throw new NullPointerException("no !/ in spec"); } try { String testSpec = spec.substring(0, bangSlash - 1); URI uri = new URI(testSpec); // verify the scheme is the JCR Repository Scheme if (!URLFactory.REPOSITORY_SCHEME.equals(uri.getScheme())) { throw new URISyntaxException(testSpec, "Unsupported Scheme " + uri.getScheme(), 0); } } catch (URISyntaxException use) { throw new NullPointerException("invalid url: " + spec + " (" + use + ")"); } return spec; } /** * Merges the specification and the file part of the URL respecting the bang * slashes. If the specification starts with a slash, it is regarded as a * complete path of a archive entry and replaces an existing archive entry * specification in the url. Examples :
*

* * * *
file * spec * result *
/some/file/path.jar!/ * /some/entry/path * /some/file/path.jar!/some/entry/path *
/some/file/path.jar!/some/default * /some/entry/path * /some/file/path.jar!/some/entry/path
*

* If the specification is not absolutes it replaces the last file name part * if the file name does not end with a slash. Examples :
*

* * * *
file * spec * result *
/some/file/path.jar!/ * /some/entry/path * /some/file/path.jar!/some/entry/path *
/some/file/path.jar!/some/default * /some/entry/path * /some/file/path.jar!/some/entry/path
* * @param url The URL whose file part is used * @param spec The specification to merge with the file part * @throws NullPointerException If the specification starts with a slash and * the URL does not contain a slash bang or if the specification * does not start with a slash and the file part of the URL does * is not an absolute file path. */ private String parseContextSpec(URL url, String spec) { // spec is relative to this file String file = url.getFile(); // if the spec is absolute path, it is an absolute entry spec if (spec.startsWith("/")) { // assert the bang slash in the original URL int bangSlash = indexOfBangSlash(file); if (bangSlash == -1) { throw new NullPointerException("malformed context url:" + url + ": no !/"); } // remove bang slash part from the original file file = file.substring(0, bangSlash); } // if the file is not a directory and spec is a relative file path if (!file.endsWith("/") && !spec.startsWith("/")) { // find the start of the file name in the url file path int lastSlash = file.lastIndexOf('/'); if (lastSlash == -1) { throw new NullPointerException("malformed context url:" + url); } // cut off the file name from the URL file path file = file.substring(0, lastSlash + 1); } // concat file part and the spec now return file + spec; } public String canonizeString(String s) { int i = 0; int k = s.length(); while ((i = s.indexOf("/../")) >= 0) if ((k = s.lastIndexOf('/', i - 1)) >= 0) s = s.substring(0, k) + s.substring(i + 3); else s = s.substring(i + 3); while ((i = s.indexOf("/./")) >= 0) s = s.substring(0, i) + s.substring(i + 2); while (s.endsWith("/..")) { int j = s.indexOf("/.."); int l; if ((l = s.lastIndexOf('/', j - 1)) >= 0) s = s.substring(0, l + 1); else s = s.substring(0, j); } if (s.endsWith("/.")) s = s.substring(0, s.length() - 1); return s; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy