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 }