1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright (c) 1999 by Sun Microsystems, Inc.
23 * All rights reserved.
24 *
25 */
26
27//  Opaque.java:   Wrapper for byte[].
28//  Author:           James Kempf
29//  Created On:       Tue Apr  7 15:21:58 1998
30//  Last Modified By: James Kempf
31//  Last Modified On: Fri Jun  5 15:26:59 1998
32//  Update Count:     38
33//
34
35package com.sun.slp;
36
37import java.util.*;
38import java.io.*;
39
40/**
41 * The Opaque class wraps Java byte arrays so we can do object-like
42 * things, such as deep equality comparison and printing.
43 *
44 * @author James Kempf
45 */
46
47class Opaque extends Object {
48
49    // Character to use for fill.
50
51    private static final char ZERO = '0';
52
53    // The byte array.
54
55    byte[] bytes;
56
57    // For identifying opaques.
58
59    final static String OPAQUE_HEADER = "\\ff";
60
61    // Construct a Opaque.
62
63    Opaque(byte[] nb) {
64	bytes = nb;
65
66    }
67
68    // Construct a byte array from an escaped string.
69
70    static byte[] unescapeByteArray(String str)
71	throws ServiceLocationException {
72
73	// Check for opaque header.
74
75	if (!str.startsWith(OPAQUE_HEADER)) {
76	    throw
77		new ServiceLocationException(
78				ServiceLocationException.PARSE_ERROR,
79				"no_opaque_header",
80				new Object[] {str});
81
82	}
83
84	String string = str.substring(OPAQUE_HEADER.length());
85
86	// Process escapes to remove slash.
87	//  string.
88
89	int i, n = string.length();
90	int len = 0;
91	int nlen = n / 3;
92	byte[] b = new byte[nlen];
93
94	for (i = 0; i < n; i++) {
95	    if (string.charAt(i) != ServiceLocationAttribute.ESCAPE) {
96		throw
97		    new ServiceLocationException(
98				ServiceLocationException.PARSE_ERROR,
99				"escape_err",
100				new Object[] {str});
101
102	    }
103
104	    // Get the next two characters.
105
106	    if (i > n - 2) {
107		throw
108		    new ServiceLocationException(
109				ServiceLocationException.PARSE_ERROR,
110				"nonterminating_escape",
111				new Object[] {str});
112	    }
113
114	    if (len >= nlen) {
115		throw
116		    new ServiceLocationException(
117				ServiceLocationException.PARSE_ERROR,
118				"wrong_char_num",
119				new Object[] {str});
120	    }
121
122	    try {
123
124		i++;
125		b[len++] = (byte)(Integer.parseInt(
126				string.substring(i, i+2), 16) & 0xFF);
127		i++;
128
129	    } catch (NumberFormatException ex) {
130		throw
131		    new ServiceLocationException(
132				ServiceLocationException.PARSE_ERROR,
133				"not_hex",
134				new Object[] {str});
135
136	    }
137
138	}
139
140	return b;
141    }
142
143    // Overrides Object.equals().
144
145    public boolean equals(Object o) {
146
147	if (o == this) {
148	    return true;
149
150	}
151
152	if (!(o instanceof Opaque)) {
153	    return false;
154
155	}
156
157	byte[]  cbyte = ((Opaque)o).bytes;
158
159	// Not equal if lengths aren't.
160
161	if (cbyte.length != bytes.length) {
162	    return false;
163
164	}
165
166	// Check inside.
167
168	int i;
169
170	for (i = 0; i < cbyte.length; i++) {
171	    if (cbyte[i] != bytes[i]) {
172		return false;
173
174	    }
175	}
176
177	return true;
178    }
179
180    public String toString() {
181
182	int i, n = bytes.length;
183	StringBuffer buf = new StringBuffer();
184
185	buf.append(OPAQUE_HEADER);
186
187	for (i = 0; i < n; i++) {
188	    String str = null;
189
190	    // Convert each byte into a string, then escape. We use
191	    //  an 8-bit encoding, LATIN1, since escapes are two
192	    //  characters only.
193
194	    str = Integer.toHexString(((int)bytes[i] & 0xFF));
195
196	    buf.append(ServiceLocationAttribute.ESCAPE);
197
198	    if (str.length() < 2) {
199		buf.append(ZERO);
200	    }
201
202	    buf.append(str);
203	}
204
205	return buf.toString();
206    }
207
208}
209