001 /**
002 * <copyright>
003 *
004 * Copyright (c) 2004-2006 IBM Corporation and others.
005 * All rights reserved. This program and the accompanying materials
006 * are made available under the terms of the Eclipse Public License v1.0
007 * which accompanies this distribution, and is available at
008 * http://www.eclipse.org/legal/epl-v10.html
009 *
010 * Contributors:
011 * IBM - Initial API and implementation
012 *
013 * </copyright>
014 *
015 * $Id$
016 */
017 package org.eclipse.emf.common.archive;
018
019 import java.io.IOException;
020 import java.io.InputStream;
021 import java.net.URL;
022 import java.net.URLConnection;
023 import java.net.URLStreamHandler;
024
025 /**
026 * A URL stream handler that can be {@link #register() registered} to support archive access protocol.
027 * It uses {@link ArchiveURLConnection} to implement the connection.
028 */
029 public class Handler extends URLStreamHandler
030 {
031 /**
032 * Registers this class.
033 * A handler for protocol "xyz" is registered
034 * by providing a class named Handler implementing {@link URLStreamHandler}
035 * in a package called named xyz in a package of your choosing,
036 * and then registering that chosen prefix package name
037 * in the system property for <code>"java.protocol.handler.pkgs"</code>,
038 * which is an "|" separated list of package prefixes to search for handlers.
039 */
040 public static void register()
041 {
042 String javaProtocolHandlerPkgs = System.getProperty("java.protocol.handler.pkgs");
043 if (javaProtocolHandlerPkgs == null || javaProtocolHandlerPkgs.length() == 0)
044 {
045 javaProtocolHandlerPkgs = "org.eclipse.emf.common";
046 }
047 else
048 {
049 javaProtocolHandlerPkgs += "|org.eclipse.emf.common";
050 }
051 System.setProperty("java.protocol.handler.pkgs", javaProtocolHandlerPkgs);
052 }
053
054 /**
055 * Registers this handler and interprets each argument as URL to be opened, read in, and written out to System.out.
056 * @param args URLs to open, read, and write to System.out
057 * @throws IOException if there are problems opening or reading from the URLs, or writing to System.out.
058 */
059 public static void main(String[] args) throws IOException
060 {
061 register();
062
063 for (int i = 0; i < args.length; ++i)
064 {
065 InputStream inputStream = new URL(args[i]).openStream();
066 byte [] bytes = new byte [4048];
067 for (int size; (size = inputStream.read(bytes, 0, bytes.length)) > -1; )
068 {
069 System.out.write(bytes, 0, size);
070 }
071 }
072 }
073
074 /**
075 * Creates an instance.
076 */
077 public Handler()
078 {
079 super();
080 }
081
082 /**
083 * Overrides parsing the URL to validate constraints on well formed archive syntax.
084 * @see URLStreamHandler#parseURL(java.net.URL, java.lang.String, int, int)
085 */
086 @Override
087 protected void parseURL(URL url, String specification, int start, int limit)
088 {
089 super.parseURL(url, specification, start, limit);
090
091 // There needs to be another URL protocol right after the archive protocol, and not a "/".
092 //
093 if (start > limit || specification.charAt(start) == '/')
094 {
095 throw
096 new IllegalArgumentException
097 ("archive protocol must be immediately followed by another URL protocol " + specification);
098 }
099
100 // There must be at least one archive path.
101 //
102 int archiveSeparator = specification.indexOf("!/", start);
103 if (archiveSeparator < 0)
104 {
105 throw new IllegalArgumentException("missing archive separators " + specification.substring(start, limit));
106 }
107
108 // Parse to count the archive paths that must will be delegated to the nested URL based on the number of schemes at the start.
109 //
110 for (int i = start, end = specification.indexOf('/', start) - 1; (i = specification.indexOf(':', i)) < end; ++i)
111 {
112 // There should be at least one archive separator per scheme.
113 //
114 archiveSeparator = specification.indexOf("!/", archiveSeparator + 2);
115 if (archiveSeparator < 0)
116 {
117 throw new IllegalArgumentException("too few archive separators " + specification);
118 }
119 }
120 }
121
122 /**
123 * Returns a new {@link ArchiveURLConnection}.
124 */
125 @Override
126 protected URLConnection openConnection(URL url) throws IOException
127 {
128 return new ArchiveURLConnection(url);
129 }
130 }