View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements.  See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    * 
10   *      http://www.apache.org/licenses/LICENSE-2.0
11   * 
12   * Unless required by applicable law or agreed to in writing, software
13   * distributed under the License is distributed on an "AS IS" BASIS,
14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15   * See the License for the specific language governing permissions and
16   * limitations under the License.
17   */
18  
19  package org.apache.river.tool;
20  
21  import java.io.File;
22  import java.io.FileNotFoundException;
23  import java.net.MalformedURLException;
24  import java.net.URL;
25  import java.text.MessageFormat;
26  import java.util.MissingResourceException;
27  import java.util.ResourceBundle;
28  import net.jini.url.httpmd.Handler;
29  import net.jini.url.httpmd.HttpmdUtil;
30  
31  /**
32   * Computes the message digests for a codebase with HTTPMD URLs. This utility
33   * is run from the {@linkplain #main command line}. <p>
34   * A description of HTTPMD URLs can be found in the {@link net.jini.url.httpmd}
35   * package and its {@link net.jini.url.httpmd.Handler} class.<p>
36   *
37   * An example command line (shown with lines wrapped for readability) is:
38   *
39   * <blockquote>
40   * <pre>
41   * java -jar <var><b>install_dir</b></var>/lib/computehttpmdcodebase.jar \
42   *      <var><b>install_dir</b></var>/lib-dl \
43   *      "httpmd://<var><b>your_host</b></var>:<var><b>http_port</b></var>/sdm-dl.jar;md5=0"
44   * </pre>
45   * </blockquote>
46   *
47   * where <var><b>install_dir</b></var> is the directory where the JGDMS release
48   * is installed, <var><b>your_host</b></var> is the host where the HTTP server
49   * for the <code>sdm-dl.jar</code> JAR file will be running, and
50   * <var><b>http_port</b></var> is the port for that server. This command prints
51   * out the download codebase for use by a client that uses the <code>
52   * net.jini.lookup.ServiceDiscoveryManager</code>, using an HTTPMD URL to guarantee
53   * integrity for the classes in the <code>sdm-dl.jar</code> JAR file. The
54   * message digest will be computed using the <code>md5</code> algorithm, and
55   * the <code>0</code> will be replaced by the computed digest.
56   *
57   * @author Sun Microsystems, Inc.
58   * @since 2.0
59   */
60  public class ComputeHttpmdCodebase {
61      private static ResourceBundle resources;
62      private static boolean resinit = false;
63  
64      private ComputeHttpmdCodebase() { }
65  
66      /**
67       * Computes the message digests for a codebase made up of HTTPMD URLs.
68       * The command line arguments are:
69       * <pre>
70       * <var><b>source-directory</b></var> <var><b>url</b></var>...
71       * </pre>
72       * The first argument is the filename or URL of the directory containing
73       * the source files for the HTTPMD URLs. The remaining arguments specify
74       * the HTTPMD URLs that make up the codebase. The digest values specified
75       * in the HTTPMD URLs will be ignored (zeroes are typically used). The
76       * path portion of each HTTPMD URL, without the message digest parameters,
77       * names a source file relative to the source directory; the message
78       * digest for that source file is computed and replaces the digest value
79       * in the HTTPMD URL. The resulting HTTPMD URLs are printed, separated by
80       * spaces.
81       * <p>
82       * Do not use a directory on a remote filesystem, or a directory URL, if
83       * the underlying network access protocol does not provide adequate data
84       * integrity or authentication of the remote host.
85       */
86      public static void main(String[] args) {
87  	if (args.length < 2) {
88  	    print("computecodebase.usage", (String) null);
89  	    System.exit(1);
90  	}
91  	Handler handler = new Handler();
92  	StringBuffer codebase = new StringBuffer();
93  	try {
94  	    boolean isURL;
95  	    URL base;
96  	    try {
97  		base = new URL(args[0].endsWith("/") ?
98  			       args[0] : args[0] + "/");
99  		isURL = true;
100 	    } catch (MalformedURLException e) {
101 		File sourceDirectory = new File(args[0]);
102 		if (!sourceDirectory.isDirectory()) {
103 		    print("computecodebase.notdir", args[0]);
104 		    System.exit(1);
105 		}
106 		base = sourceDirectory.toURI().toURL();
107 		isURL = false;
108 	    }
109 	    for (int i = 1; i < args.length; i++) {
110 		String spec = args[i];
111 		if (!"httpmd:".regionMatches(true, 0, spec, 0, 7)) {
112 		    print("computecodebase.nonhttpmd", spec);
113 		    System.exit(1);
114 		}
115 		URL url;
116 		try {
117 		    url = new URL(null, spec, handler);
118 		} catch (MalformedURLException e) {
119 		    print("computecodebase.badurl",
120 			  new String[]{spec, e.getLocalizedMessage()});
121 		    System.exit(1);
122 		    return; // not reached, make compiler happy
123 		}
124 		String path = url.getPath();
125 		int paramIndex = path.lastIndexOf(';');
126 		int equalsIndex = path.indexOf('=', paramIndex);
127 		int commentIndex = path.indexOf(',', equalsIndex);
128 		String algorithm = path.substring(paramIndex + 1, equalsIndex);
129 		URL source =
130 		    new URL(base,
131 			    path.substring(path.startsWith("/") ? 1 : 0,
132 					   path.indexOf(';')));
133 		String digest;
134 		try {
135 		    digest = HttpmdUtil.computeDigest(source, algorithm);
136 		} catch (FileNotFoundException e) {
137 		    print("computecodebase.notfound",
138 			  isURL ? source.toExternalForm() : source.getPath());
139 		    System.exit(1);
140 		    return; // not reached, make compiler happy
141 		}
142 		URL result = new URL(
143 		    url,
144 		    path.substring(0, equalsIndex + 1) + digest +
145 		    (commentIndex < 0 ? "" : path.substring(commentIndex)) +
146 		    (url.getQuery() == null ? "" : '?' + url.getQuery()) +
147 		    (url.getRef() == null ? "" : '#' + url.getRef()));
148 		if (codebase.length() > 0) {
149 		    codebase.append(' ');
150 		}
151 		codebase.append(result);
152 	    }
153 	} catch (Throwable t) {
154 	    t.printStackTrace();
155 	    System.exit(1);
156 	}
157 	System.out.println(codebase);
158     }
159 
160     private static synchronized String getString(String key) {
161 	try {
162 	    if (!resinit) {
163 		resources = ResourceBundle.getBundle(
164 			       "org.apache.river.tool.resources.computecodebase");
165 		resinit = true;
166 	    }
167 	    return resources.getString(key);
168 	} catch (MissingResourceException e) {
169 	    e.printStackTrace();
170 	    System.err.println("Unable to find a required resource.");
171 	    System.exit(1);
172 	    return null;
173 	}
174     }
175 
176     private static void print(String key, String val) {
177 	print(key, new String[]{val});
178     }
179 
180     private static void print(String key, String[] vals) {
181 	String fmt = getString(key);
182 	if (fmt == null)
183 	    fmt = "no text found: \"" + key + "\" {0}";
184 	System.err.println(MessageFormat.format(fmt, vals));
185     }
186 }