1a5b190bfSAndrew Rist /**************************************************************
2a5b190bfSAndrew Rist  *
3a5b190bfSAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4a5b190bfSAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5a5b190bfSAndrew Rist  * distributed with this work for additional information
6a5b190bfSAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7a5b190bfSAndrew Rist  * to you under the Apache License, Version 2.0 (the
8a5b190bfSAndrew Rist  * "License"); you may not use this file except in compliance
9a5b190bfSAndrew Rist  * with the License.  You may obtain a copy of the License at
10a5b190bfSAndrew Rist  *
11a5b190bfSAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12a5b190bfSAndrew Rist  *
13a5b190bfSAndrew Rist  * Unless required by applicable law or agreed to in writing,
14a5b190bfSAndrew Rist  * software distributed under the License is distributed on an
15a5b190bfSAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16a5b190bfSAndrew Rist  * KIND, either express or implied.  See the License for the
17a5b190bfSAndrew Rist  * specific language governing permissions and limitations
18a5b190bfSAndrew Rist  * under the License.
19a5b190bfSAndrew Rist  *
20a5b190bfSAndrew Rist  *************************************************************/
21a5b190bfSAndrew Rist 
22a5b190bfSAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir package com.sun.star.lib.uno.helper;
25cdf0e10cSrcweir import java.io.UnsupportedEncodingException;
26cdf0e10cSrcweir import java.util.HashMap;
27cdf0e10cSrcweir import java.util.Vector;
28cdf0e10cSrcweir 
29cdf0e10cSrcweir /**
30cdf0e10cSrcweir  * Object representation and parsing of Uno Urls,
31cdf0e10cSrcweir  * which allow to locate a named Uno object in a
32cdf0e10cSrcweir  * different process. An Uno Url consists of the
33cdf0e10cSrcweir  * specification of a connection, protocol and
34cdf0e10cSrcweir  * rootOid delimited with a ';'.
35cdf0e10cSrcweir  * The syntax of an Uno Url is
36cdf0e10cSrcweir  *
37cdf0e10cSrcweir  * <code>
38cdf0e10cSrcweir  * [uno:]connection-type,parameters;protocol-name,parameters;objectname";
39cdf0e10cSrcweir  * </code>
40cdf0e10cSrcweir  *
41cdf0e10cSrcweir  * An example Uno Url will look like this:
42cdf0e10cSrcweir  *
43cdf0e10cSrcweir  * <code>
44cdf0e10cSrcweir  * socket,host=localhost,port=2002;urp;StarOffice.ServiceManager
45cdf0e10cSrcweir  * </code>
46cdf0e10cSrcweir  *
47cdf0e10cSrcweir  * For more information about Uno Url please consult
48cdf0e10cSrcweir  * <a href="http://udk.openoffice.org/common/man/spec/uno-url.html">
49cdf0e10cSrcweir  * http://udk.openoffice.org/common/man/spec/uno-url.html</a>
50cdf0e10cSrcweir  *
51cdf0e10cSrcweir  * Usage:
52cdf0e10cSrcweir  *
53cdf0e10cSrcweir  * <code>
54cdf0e10cSrcweir  *   UnoUrl url = UnoUrl.parseUnoUrl("socket,host=localhost,port=2002;urp;StarOffice.ServiceManager");
55cdf0e10cSrcweir  * </code>
56cdf0e10cSrcweir  *
57cdf0e10cSrcweir  * @author Joerg Brunsmann
58cdf0e10cSrcweir  */
59cdf0e10cSrcweir public class UnoUrl {
60cdf0e10cSrcweir 
61cdf0e10cSrcweir 	private static final String FORMAT_ERROR =
62cdf0e10cSrcweir 		"syntax: [uno:]connection-type,parameters;protocol-name,parameters;objectname";
63cdf0e10cSrcweir 
64cdf0e10cSrcweir 	private static final String VALUE_CHAR_SET = "!$&'()*+-./:?@_~";
65cdf0e10cSrcweir 	private static final String OID_CHAR_SET = VALUE_CHAR_SET + ",=";
66cdf0e10cSrcweir 
67cdf0e10cSrcweir 	private UnoUrlPart connection;
68cdf0e10cSrcweir 	private UnoUrlPart protocol;
69cdf0e10cSrcweir 	private String rootOid;
70cdf0e10cSrcweir 
71cdf0e10cSrcweir 	static private class UnoUrlPart {
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 		private String partTypeName;
74cdf0e10cSrcweir 		private HashMap partParameters;
75cdf0e10cSrcweir 		private String uninterpretedParameterString;
76cdf0e10cSrcweir 
UnoUrlPart( String uninterpretedParameterString, String partTypeName, HashMap partParameters)77cdf0e10cSrcweir 		public UnoUrlPart(
78cdf0e10cSrcweir 			String uninterpretedParameterString,
79cdf0e10cSrcweir 			String partTypeName,
80cdf0e10cSrcweir 			HashMap partParameters) {
81cdf0e10cSrcweir 			this.uninterpretedParameterString = uninterpretedParameterString;
82cdf0e10cSrcweir 			this.partTypeName = partTypeName;
83cdf0e10cSrcweir 			this.partParameters = partParameters;
84cdf0e10cSrcweir 		}
85cdf0e10cSrcweir 
getPartTypeName()86cdf0e10cSrcweir 		public String getPartTypeName() {
87cdf0e10cSrcweir 			return partTypeName;
88cdf0e10cSrcweir 		}
89cdf0e10cSrcweir 
getPartParameters()90cdf0e10cSrcweir 		public HashMap getPartParameters() {
91cdf0e10cSrcweir 			return partParameters;
92cdf0e10cSrcweir 		}
93cdf0e10cSrcweir 
getUninterpretedParameterString()94cdf0e10cSrcweir 		public String getUninterpretedParameterString() {
95cdf0e10cSrcweir 			return uninterpretedParameterString;
96cdf0e10cSrcweir 		}
97cdf0e10cSrcweir 
getUninterpretedString()98cdf0e10cSrcweir         public String getUninterpretedString() {
99cdf0e10cSrcweir             StringBuffer buf = new StringBuffer(partTypeName);
100cdf0e10cSrcweir             if (uninterpretedParameterString.length() > 0) {
101cdf0e10cSrcweir                 buf.append(',');
102cdf0e10cSrcweir                 buf.append(uninterpretedParameterString);
103cdf0e10cSrcweir             }
104cdf0e10cSrcweir             return buf.toString();
105cdf0e10cSrcweir         }
106cdf0e10cSrcweir 	}
107cdf0e10cSrcweir 
UnoUrl( UnoUrlPart connectionPart, UnoUrlPart protocolPart, String rootOid)108cdf0e10cSrcweir 	private UnoUrl(
109cdf0e10cSrcweir 		UnoUrlPart connectionPart,
110cdf0e10cSrcweir 		UnoUrlPart protocolPart,
111cdf0e10cSrcweir 		String rootOid) {
112cdf0e10cSrcweir 		this.connection = connectionPart;
113cdf0e10cSrcweir 		this.protocol = protocolPart;
114cdf0e10cSrcweir 		this.rootOid = rootOid;
115cdf0e10cSrcweir 	}
116cdf0e10cSrcweir 
117cdf0e10cSrcweir 	/**
118cdf0e10cSrcweir 	 * Returns the name of the connection of this
119cdf0e10cSrcweir 	 * Uno Url. Encoded characters are not allowed.
120cdf0e10cSrcweir 	 *
121cdf0e10cSrcweir 	 * @return The connection name as string.
122cdf0e10cSrcweir 	 */
getConnection()123cdf0e10cSrcweir 	public String getConnection() {
124cdf0e10cSrcweir 		return connection.getPartTypeName();
125cdf0e10cSrcweir 	}
126cdf0e10cSrcweir 
127cdf0e10cSrcweir 	/**
128cdf0e10cSrcweir 	 * Returns the name of the protocol of this
129cdf0e10cSrcweir 	 * Uno Url. Encoded characters are not allowed.
130cdf0e10cSrcweir 	 *
131cdf0e10cSrcweir 	 * @return The protocol name as string.
132cdf0e10cSrcweir 	 */
getProtocol()133cdf0e10cSrcweir 	public String getProtocol() {
134cdf0e10cSrcweir 		return protocol.getPartTypeName();
135cdf0e10cSrcweir 	}
136cdf0e10cSrcweir 
137cdf0e10cSrcweir 	/**
138cdf0e10cSrcweir 	 * Return the object name. Encoded character are
139cdf0e10cSrcweir 	 * not allowed.
140cdf0e10cSrcweir 	 *
141cdf0e10cSrcweir 	 * @return The object name as String.
142cdf0e10cSrcweir 	 */
getRootOid()143cdf0e10cSrcweir 	public String getRootOid() {
144cdf0e10cSrcweir 		return rootOid;
145cdf0e10cSrcweir 	}
146cdf0e10cSrcweir 
147cdf0e10cSrcweir 	/**
148cdf0e10cSrcweir 	 * Returns the protocol parameters as
149cdf0e10cSrcweir 	 * a Hashmap with key/value pairs. Encoded
150cdf0e10cSrcweir 	 * characters like '%41' are decoded.
151cdf0e10cSrcweir 	 *
152cdf0e10cSrcweir 	 * @return a HashMap with key/value pairs for protocol parameters.
153cdf0e10cSrcweir 	 */
getProtocolParameters()154cdf0e10cSrcweir 	public HashMap getProtocolParameters() {
155cdf0e10cSrcweir 		return protocol.getPartParameters();
156cdf0e10cSrcweir 	}
157cdf0e10cSrcweir 
158cdf0e10cSrcweir 	/**
159cdf0e10cSrcweir 	 * Returns the connection parameters as
160cdf0e10cSrcweir 	 * a Hashmap with key/value pairs. Encoded
161cdf0e10cSrcweir 	 * characters like '%41' are decoded.
162cdf0e10cSrcweir 	 *
163cdf0e10cSrcweir 	 * @return a HashMap with key/value pairs for connection parameters.
164cdf0e10cSrcweir 	 */
getConnectionParameters()165cdf0e10cSrcweir 	public HashMap getConnectionParameters() {
166cdf0e10cSrcweir 		return connection.getPartParameters();
167cdf0e10cSrcweir 	}
168cdf0e10cSrcweir 
169cdf0e10cSrcweir 	/**
170cdf0e10cSrcweir 	 * Returns the raw specification of the protocol
171cdf0e10cSrcweir 	 * parameters. Encoded characters like '%41' are
172cdf0e10cSrcweir 	 * not decoded.
173cdf0e10cSrcweir 	 *
174cdf0e10cSrcweir 	 * @return The uninterpreted protocol parameters as string.
175cdf0e10cSrcweir 	 */
getProtocolParametersAsString()176cdf0e10cSrcweir 	public String getProtocolParametersAsString() {
177cdf0e10cSrcweir 		return protocol.getUninterpretedParameterString();
178cdf0e10cSrcweir 	}
179cdf0e10cSrcweir 
180cdf0e10cSrcweir 	/**
181cdf0e10cSrcweir 	 * Returns the raw specification of the connection
182cdf0e10cSrcweir 	 * parameters. Encoded characters like '%41' are
183cdf0e10cSrcweir 	 * not decoded.
184cdf0e10cSrcweir 	 *
185cdf0e10cSrcweir 	 * @return The uninterpreted connection parameters as string.
186cdf0e10cSrcweir 	 */
getConnectionParametersAsString()187cdf0e10cSrcweir 	public String getConnectionParametersAsString() {
188cdf0e10cSrcweir 		return connection.getUninterpretedParameterString();
189cdf0e10cSrcweir 	}
190cdf0e10cSrcweir 
191cdf0e10cSrcweir     /**
192cdf0e10cSrcweir      * Returns the raw specification of the protocol
193cdf0e10cSrcweir      * name and parameters. Encoded characters like '%41' are
194cdf0e10cSrcweir      * not decoded.
195cdf0e10cSrcweir      *
196cdf0e10cSrcweir      * @return The uninterpreted protocol name and parameters as string.
197cdf0e10cSrcweir      */
getProtocolAndParametersAsString()198cdf0e10cSrcweir     public String getProtocolAndParametersAsString() {
199cdf0e10cSrcweir         return protocol.getUninterpretedString();
200cdf0e10cSrcweir     }
201cdf0e10cSrcweir 
202cdf0e10cSrcweir     /**
203cdf0e10cSrcweir      * Returns the raw specification of the connection
204cdf0e10cSrcweir      * name and parameters. Encoded characters like '%41' are
205cdf0e10cSrcweir      * not decoded.
206cdf0e10cSrcweir      *
207cdf0e10cSrcweir      * @return The uninterpreted connection name and parameters as string.
208cdf0e10cSrcweir      */
getConnectionAndParametersAsString()209cdf0e10cSrcweir     public String getConnectionAndParametersAsString() {
210cdf0e10cSrcweir         return connection.getUninterpretedString();
211cdf0e10cSrcweir     }
212cdf0e10cSrcweir 
hexToInt(int ch)213cdf0e10cSrcweir 	private static int hexToInt(int ch)
214cdf0e10cSrcweir 		throws com.sun.star.lang.IllegalArgumentException {
215cdf0e10cSrcweir 		int c = Character.toLowerCase((char) ch);
216cdf0e10cSrcweir 		boolean isDigit = ('0' <= c && c <= '9');
217cdf0e10cSrcweir 		boolean isValidChar = ('a' <= c && c <= 'f') || isDigit;
218cdf0e10cSrcweir 
219cdf0e10cSrcweir 		if (!isValidChar)
220cdf0e10cSrcweir 			throw new com.sun.star.lang.IllegalArgumentException(
221cdf0e10cSrcweir 				"Invalid UTF-8 hex byte '" + c + "'.");
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 		return isDigit ? ch - '0' : 10 + ((char) c - 'a') & 0xF;
224cdf0e10cSrcweir 	}
225cdf0e10cSrcweir 
decodeUTF8(String s)226cdf0e10cSrcweir 	private static String decodeUTF8(String s)
227cdf0e10cSrcweir 		throws com.sun.star.lang.IllegalArgumentException {
228cdf0e10cSrcweir 		Vector v = new Vector();
229cdf0e10cSrcweir 
230cdf0e10cSrcweir 		for (int i = 0; i < s.length(); i++) {
231cdf0e10cSrcweir 			int ch = s.charAt(i);
232cdf0e10cSrcweir 
233cdf0e10cSrcweir 			if (ch == '%') {
234cdf0e10cSrcweir 				int hb = hexToInt(s.charAt(++i));
235cdf0e10cSrcweir 				int lb = hexToInt(s.charAt(++i));
236cdf0e10cSrcweir 				ch = (hb << 4) | lb;
237cdf0e10cSrcweir 			}
238cdf0e10cSrcweir 
239*5b5659a7SDamjan Jovanovic 			v.addElement(ch);
240cdf0e10cSrcweir 		}
241cdf0e10cSrcweir 
242cdf0e10cSrcweir 		int size = v.size();
243cdf0e10cSrcweir 		byte[] bytes = new byte[size];
244cdf0e10cSrcweir 		for (int i = 0; i < size; i++) {
245cdf0e10cSrcweir 			Integer anInt = (Integer) v.elementAt(i);
246cdf0e10cSrcweir 			bytes[i] = (byte) (anInt.intValue() & 0xFF);
247cdf0e10cSrcweir 		}
248cdf0e10cSrcweir 
249cdf0e10cSrcweir 		try {
250cdf0e10cSrcweir 			return new String(bytes, "UTF-8");
251cdf0e10cSrcweir 		} catch (UnsupportedEncodingException e) {
252cdf0e10cSrcweir 			throw new com.sun.star.lang.IllegalArgumentException(
253cdf0e10cSrcweir 				"Couldn't convert parameter string to UTF-8 string:" + e.getMessage());
254cdf0e10cSrcweir 		}
255cdf0e10cSrcweir 	}
256cdf0e10cSrcweir 
buildParamHashMap(String paramString)257cdf0e10cSrcweir 	private static HashMap buildParamHashMap(String paramString)
258cdf0e10cSrcweir 		throws com.sun.star.lang.IllegalArgumentException {
259cdf0e10cSrcweir 		HashMap params = new HashMap();
260cdf0e10cSrcweir 
261cdf0e10cSrcweir 		int pos = 0;
262cdf0e10cSrcweir 
263cdf0e10cSrcweir 		while (true) {
264cdf0e10cSrcweir 			char c = ',';
265cdf0e10cSrcweir 			String aKey = "";
266cdf0e10cSrcweir 			String aValue = "";
267cdf0e10cSrcweir 
268cdf0e10cSrcweir 			while ((pos < paramString.length())
269cdf0e10cSrcweir 				&& ((c = paramString.charAt(pos++)) != '=')) {
270cdf0e10cSrcweir 				aKey += c;
271cdf0e10cSrcweir 			}
272cdf0e10cSrcweir 
273cdf0e10cSrcweir 			while ((pos < paramString.length())
274cdf0e10cSrcweir 				&& ((c = paramString.charAt(pos++)) != ',')
275cdf0e10cSrcweir 				&& c != ';') {
276cdf0e10cSrcweir 				aValue += c;
277cdf0e10cSrcweir 			}
278cdf0e10cSrcweir 
279cdf0e10cSrcweir 			if ((aKey.length() > 0) && (aValue.length() > 0)) {
280cdf0e10cSrcweir 
281cdf0e10cSrcweir 				if (!isAlphaNumeric(aKey)) {
282cdf0e10cSrcweir 					throw new com.sun.star.lang.IllegalArgumentException(
283cdf0e10cSrcweir 						"The parameter key '"
284cdf0e10cSrcweir 							+ aKey
285cdf0e10cSrcweir 							+ "' may only consist of alpha numeric ASCII characters.");
286cdf0e10cSrcweir 				}
287cdf0e10cSrcweir 
288cdf0e10cSrcweir 				if (!isValidString(aValue, VALUE_CHAR_SET + "%")) {
289cdf0e10cSrcweir 					throw new com.sun.star.lang.IllegalArgumentException(
290cdf0e10cSrcweir 						"The parameter value for key '" + aKey + "' contains illegal characters.");
291cdf0e10cSrcweir 				}
292cdf0e10cSrcweir 
293cdf0e10cSrcweir 				params.put(aKey, decodeUTF8(aValue));
294cdf0e10cSrcweir 			}
295cdf0e10cSrcweir 
296cdf0e10cSrcweir 			if ((pos >= paramString.length()) || (c != ','))
297cdf0e10cSrcweir 				break;
298cdf0e10cSrcweir 
299cdf0e10cSrcweir 		}
300cdf0e10cSrcweir 
301cdf0e10cSrcweir 		return params;
302cdf0e10cSrcweir 	}
303cdf0e10cSrcweir 
parseUnoUrlPart(String thePart)304cdf0e10cSrcweir 	private static UnoUrlPart parseUnoUrlPart(String thePart)
305cdf0e10cSrcweir 		throws com.sun.star.lang.IllegalArgumentException {
306cdf0e10cSrcweir 		String partName = thePart;
307cdf0e10cSrcweir 		String theParamPart = "";
308cdf0e10cSrcweir 		int index = thePart.indexOf(",");
309cdf0e10cSrcweir 		if (index != -1) {
310cdf0e10cSrcweir 			partName = thePart.substring(0, index).trim();
311cdf0e10cSrcweir 			theParamPart = thePart.substring(index + 1).trim();
312cdf0e10cSrcweir 		}
313cdf0e10cSrcweir 
314cdf0e10cSrcweir 		if (!isAlphaNumeric(partName)) {
315cdf0e10cSrcweir 			throw new com.sun.star.lang.IllegalArgumentException(
316cdf0e10cSrcweir 				"The part name '"
317cdf0e10cSrcweir 					+ partName
318cdf0e10cSrcweir 					+ "' may only consist of alpha numeric ASCII characters.");
319cdf0e10cSrcweir 		}
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 		HashMap params = buildParamHashMap(theParamPart);
322cdf0e10cSrcweir 
323cdf0e10cSrcweir 		return new UnoUrlPart(theParamPart, partName, params);
324cdf0e10cSrcweir 	}
325cdf0e10cSrcweir 
isAlphaNumeric(String s)326cdf0e10cSrcweir 	private static boolean isAlphaNumeric(String s) {
327cdf0e10cSrcweir 		return isValidString(s, null);
328cdf0e10cSrcweir 	}
329cdf0e10cSrcweir 
isValidString(String identifier, String validCharSet)330cdf0e10cSrcweir 	private static boolean isValidString(String identifier, String validCharSet) {
331cdf0e10cSrcweir 
332cdf0e10cSrcweir 		int len = identifier.length();
333cdf0e10cSrcweir 
334cdf0e10cSrcweir 		for (int i = 0; i < len; i++) {
335cdf0e10cSrcweir 
336cdf0e10cSrcweir 			int ch = identifier.charAt(i);
337cdf0e10cSrcweir 
338cdf0e10cSrcweir 			boolean isValidChar =
339cdf0e10cSrcweir 				('A' <= ch && ch <= 'Z')
340cdf0e10cSrcweir 					|| ('a' <= ch && ch <= 'z')
341cdf0e10cSrcweir 					|| ('0' <= ch && ch <= '9');
342cdf0e10cSrcweir 
343cdf0e10cSrcweir 			if (!isValidChar && (validCharSet != null)) {
344cdf0e10cSrcweir 				isValidChar = (validCharSet.indexOf(ch) != -1);
345cdf0e10cSrcweir 			}
346cdf0e10cSrcweir 
347cdf0e10cSrcweir 			if (!isValidChar)
348cdf0e10cSrcweir 				return false;
349cdf0e10cSrcweir 		}
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 		return true;
352cdf0e10cSrcweir 	}
353cdf0e10cSrcweir 
354cdf0e10cSrcweir 	/**
355cdf0e10cSrcweir 	 * Parses the given Uno Url and returns
356cdf0e10cSrcweir 	 * an in memory object representation.
357cdf0e10cSrcweir 	 *
358cdf0e10cSrcweir 	 * @param unoUrl The given uno URl as string.
359cdf0e10cSrcweir 	 * @return Object representation of class UnoUrl.
360cdf0e10cSrcweir 	 * @throws IllegalArgumentException if Url cannot be parsed.
361cdf0e10cSrcweir 	 */
parseUnoUrl(String unoUrl)362cdf0e10cSrcweir 	public static UnoUrl parseUnoUrl(String unoUrl)
363cdf0e10cSrcweir 		throws com.sun.star.lang.IllegalArgumentException {
364cdf0e10cSrcweir 
365cdf0e10cSrcweir 		String url = unoUrl;
366cdf0e10cSrcweir 
367cdf0e10cSrcweir 		int index = url.indexOf(':');
368cdf0e10cSrcweir 		if (index != -1) {
369cdf0e10cSrcweir 			String unoStr = url.substring(0, index).trim();
370cdf0e10cSrcweir 			if (!"uno".equals(unoStr)) {
371cdf0e10cSrcweir 				throw new com.sun.star.lang.IllegalArgumentException(
372cdf0e10cSrcweir 					"Uno Urls must start with 'uno:'. " + FORMAT_ERROR);
373cdf0e10cSrcweir 			}
374cdf0e10cSrcweir 		}
375cdf0e10cSrcweir 
376cdf0e10cSrcweir 		url = url.substring(index + 1).trim();
377cdf0e10cSrcweir 
378cdf0e10cSrcweir 		index = url.indexOf(';');
379cdf0e10cSrcweir 		if (index == -1) {
380cdf0e10cSrcweir 			throw new com.sun.star.lang.IllegalArgumentException("'"+unoUrl+"' is an invalid Uno Url. " + FORMAT_ERROR);
381cdf0e10cSrcweir 		}
382cdf0e10cSrcweir 
383cdf0e10cSrcweir 		String connection = url.substring(0, index).trim();
384cdf0e10cSrcweir 		url = url.substring(index + 1).trim();
385cdf0e10cSrcweir 
386cdf0e10cSrcweir 		UnoUrlPart connectionPart = parseUnoUrlPart(connection);
387cdf0e10cSrcweir 
388cdf0e10cSrcweir 		index = url.indexOf(';');
389cdf0e10cSrcweir 		if (index == -1) {
390cdf0e10cSrcweir 			throw new com.sun.star.lang.IllegalArgumentException("'"+unoUrl+"' is an invalid Uno Url. " + FORMAT_ERROR);
391cdf0e10cSrcweir 		}
392cdf0e10cSrcweir 
393cdf0e10cSrcweir 		String protocol = url.substring(0, index).trim();
394cdf0e10cSrcweir 		url = url.substring(index + 1).trim();
395cdf0e10cSrcweir 
396cdf0e10cSrcweir 		UnoUrlPart protocolPart = parseUnoUrlPart(protocol);
397cdf0e10cSrcweir 
398cdf0e10cSrcweir 		String rootOid = url.trim();
399cdf0e10cSrcweir 		if (!isValidString(rootOid, OID_CHAR_SET)) {
400cdf0e10cSrcweir 			throw new com.sun.star.lang.IllegalArgumentException(
401cdf0e10cSrcweir 				"Root OID '"+ rootOid + "' contains illegal characters.");
402cdf0e10cSrcweir 		}
403cdf0e10cSrcweir 
404cdf0e10cSrcweir 		return new UnoUrl(connectionPart, protocolPart, rootOid);
405cdf0e10cSrcweir 
406cdf0e10cSrcweir 	}
407cdf0e10cSrcweir 
408cdf0e10cSrcweir }
409