/* * 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 net.jini.url.httpmd; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.MalformedURLException; import java.net.URL; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; /** * An HTTP URL connection for HTTPMD URLs. * * @author Sun Microsystems, Inc. * */ class HttpmdURLConnection extends DelegatingHttpURLConnection { /** The message digest algorithm. */ private final String algorithm; /** The expected message digest for the URL data. */ private final byte[] expectedDigest; /** The URL specifying the location of the data. */ private final URL content; /** Creates an HTTP URL connection for an HTTPMD URL. */ HttpmdURLConnection(URL url) throws IOException, MalformedURLException { super(url); /* Check syntax of message digest parameter */ String path = url.getPath() == null ? "" : url.getPath(); int semiIndex = path.lastIndexOf(';'); if (semiIndex < 0) { throw new MalformedURLException( "Message digest parameter is missing"); } int equalsIndex = path.indexOf('=', semiIndex); if (equalsIndex < 0) { throw new MalformedURLException( "Message digest parameter is missing a '='"); } algorithm = path.substring(semiIndex + 1, equalsIndex); try { MessageDigest.getInstance(algorithm); } catch (NoSuchAlgorithmException e) { MalformedURLException t = new MalformedURLException( "Message digest parameter algorithm is not found: " + algorithm); t.initCause(e); throw t; } String digest = path.substring(equalsIndex + 1); int comment = digest.indexOf(','); if (comment >= 0) { for (int i = digest.length(); --i > comment; ) { char c = digest.charAt(i); if (!HttpmdUtil.commentChar(c)) { throw new MalformedURLException( "Comment contains illegal character: '" + c + "'"); } } digest = digest.substring(0, comment); } int length = digest.length(); if (length == 0) { throw new MalformedURLException( "Message digest parameter digest is empty"); } try { expectedDigest = HttpmdUtil.stringDigest(digest); } catch (NumberFormatException e) { MalformedURLException t = new MalformedURLException( "Message digest parameter has invalid format for digest: " + digest); t.initCause(e); throw t; } try { content = new URL( "http", url.getHost(), url.getPort(), path.substring(0, semiIndex) + (url.getQuery() == null ? "" : url.getQuery()) + (url.getRef() == null ? "" : url.getRef())); } catch (MalformedURLException e) { MalformedURLException t = new MalformedURLException( "Problem with content location"); t.initCause(e); throw t; } delegateConnection = (HttpURLConnection) content.openConnection(); } /** Returns our URL, not the one for the HTTP connection. */ public URL getURL() { return url; } /** * Returns an input stream that uses MdInputStream to check that the input * has the expected message digest. */ public InputStream getInputStream() throws IOException { try { return new MdInputStream(url, delegateConnection.getInputStream(), MessageDigest.getInstance(algorithm), expectedDigest); } catch (NoSuchAlgorithmException e) { IOException t = new IOException( "Message digest algorithm not found: " + algorithm); t.initCause(e); throw t; } } }