update credits
[LibreOffice.git] / javaunohelper / com / sun / star / lib / uno / helper / UnoUrl.java
blobca5e7a0aadd214507138f952dabb05e9aed70060
1 /*
2 * This file is part of the LibreOffice project.
4 * This Source Code Form is subject to the terms of the Mozilla Public
5 * License, v. 2.0. If a copy of the MPL was not distributed with this
6 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 * This file incorporates work covered by the following license notice:
10 * Licensed to the Apache Software Foundation (ASF) under one or more
11 * contributor license agreements. See the NOTICE file distributed
12 * with this work for additional information regarding copyright
13 * ownership. The ASF licenses this file to you under the Apache
14 * License, Version 2.0 (the "License"); you may not use this file
15 * except in compliance with the License. You may obtain a copy of
16 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
19 package com.sun.star.lib.uno.helper;
20 import java.io.UnsupportedEncodingException;
21 import java.nio.ByteBuffer;
22 import java.util.HashMap;
24 /**
25 * Object representation and parsing of Uno Urls,
26 * which allow to locate a named Uno object in a
27 * different process. An Uno Url consists of the
28 * specification of a connection, protocol and
29 * rootOid delimited with a ';'.
30 * The syntax of an Uno Url is
32 * <code>
33 * [uno:]connection-type,parameters;protocol-name,parameters;objectname";
34 * </code>
36 * An example Uno Url will look like this:
38 * <code>
39 * socket,host=localhost,port=2002;urp;StarOffice.ServiceManager
40 * </code>
42 * For more information about Uno Url please consult
43 * <a href="http://udk.openoffice.org/common/man/spec/uno-url.html">
44 * http://udk.openoffice.org/common/man/spec/uno-url.html</a>
46 * Usage:
48 * <code>
49 * UnoUrl url = UnoUrl.parseUnoUrl("socket,host=localhost,port=2002;urp;StarOffice.ServiceManager");
50 * </code>
52 public class UnoUrl {
54 private static final String FORMAT_ERROR =
55 "syntax: [uno:]connection-type,parameters;protocol-name,parameters;objectname";
57 private static final String VALUE_CHAR_SET = "!$&'()*+-./:?@_~";
58 private static final String OID_CHAR_SET = VALUE_CHAR_SET + ",=";
60 private final UnoUrlPart connection;
61 private final UnoUrlPart protocol;
62 private final String rootOid;
64 static private class UnoUrlPart {
66 private final String partTypeName;
67 private final HashMap<String,String> partParameters;
68 private final String uninterpretedParameterString;
70 public UnoUrlPart(
71 String uninterpretedParameterString,
72 String partTypeName,
73 HashMap<String,String> partParameters) {
74 this.uninterpretedParameterString = uninterpretedParameterString;
75 this.partTypeName = partTypeName;
76 this.partParameters = partParameters;
79 public String getPartTypeName() {
80 return partTypeName;
83 public HashMap<String,String> getPartParameters() {
84 return partParameters;
87 public String getUninterpretedParameterString() {
88 return uninterpretedParameterString;
91 public String getUninterpretedString() {
92 StringBuffer buf = new StringBuffer(partTypeName);
93 if (uninterpretedParameterString.length() > 0) {
94 buf.append(',');
95 buf.append(uninterpretedParameterString);
97 return buf.toString();
101 private UnoUrl(
102 UnoUrlPart connectionPart,
103 UnoUrlPart protocolPart,
104 String rootOid) {
105 this.connection = connectionPart;
106 this.protocol = protocolPart;
107 this.rootOid = rootOid;
111 * Returns the name of the connection of this
112 * Uno Url. Encoded characters are not allowed.
114 * @return The connection name as string.
116 public String getConnection() {
117 return connection.getPartTypeName();
121 * Returns the name of the protocol of this
122 * Uno Url. Encoded characters are not allowed.
124 * @return The protocol name as string.
126 public String getProtocol() {
127 return protocol.getPartTypeName();
131 * Return the object name. Encoded character are
132 * not allowed.
134 * @return The object name as String.
136 public String getRootOid() {
137 return rootOid;
141 * Returns the protocol parameters as
142 * a Hashmap with key/value pairs. Encoded
143 * characters like '%41' are decoded.
145 * @return a HashMap with key/value pairs for protocol parameters.
147 public HashMap<String,String> getProtocolParameters() {
148 return protocol.getPartParameters();
152 * Returns the connection parameters as
153 * a Hashmap with key/value pairs. Encoded
154 * characters like '%41' are decoded.
156 * @return a HashMap with key/value pairs for connection parameters.
158 public HashMap<String,String> getConnectionParameters() {
159 return connection.getPartParameters();
163 * Returns the raw specification of the protocol
164 * parameters. Encoded characters like '%41' are
165 * not decoded.
167 * @return The uninterpreted protocol parameters as string.
169 public String getProtocolParametersAsString() {
170 return protocol.getUninterpretedParameterString();
174 * Returns the raw specification of the connection
175 * parameters. Encoded characters like '%41' are
176 * not decoded.
178 * @return The uninterpreted connection parameters as string.
180 public String getConnectionParametersAsString() {
181 return connection.getUninterpretedParameterString();
185 * Returns the raw specification of the protocol
186 * name and parameters. Encoded characters like '%41' are
187 * not decoded.
189 * @return The uninterpreted protocol name and parameters as string.
191 public String getProtocolAndParametersAsString() {
192 return protocol.getUninterpretedString();
196 * Returns the raw specification of the connection
197 * name and parameters. Encoded characters like '%41' are
198 * not decoded.
200 * @return The uninterpreted connection name and parameters as string.
202 public String getConnectionAndParametersAsString() {
203 return connection.getUninterpretedString();
206 private static String decodeUTF8(String s)
207 throws com.sun.star.lang.IllegalArgumentException {
209 try {
210 if (s.contains("%")) {
211 int length = s.length();
212 ByteBuffer bb = ByteBuffer.allocate(length);
213 for (int i = 0; i < length; i++) {
214 int ch = s.charAt(i);
216 if (ch == '%') {
217 if (i+3 > length)
218 throw new com.sun.star.lang.IllegalArgumentException(
219 "Incomplete trailing escape (%) pattern");
220 try {
221 ch = Integer.parseInt(s.substring(i+1,i+3),16);
222 } catch (NumberFormatException e) {
223 throw new com.sun.star.lang.IllegalArgumentException(e);
225 if (ch < 0)
226 throw new com.sun.star.lang.IllegalArgumentException(
227 "Illegal hex characters in escape (%) pattern - negative value");
228 i+=2;
231 bb.put((byte) (ch & 0xFF));
234 byte[] bytes = new byte[bb.position()];
235 System.arraycopy(bb.array(), 0, bytes, 0, bytes.length);
236 return new String(bytes, "UTF-8");
238 } else {
240 return new String(s.getBytes(), "UTF-8");
243 } catch (UnsupportedEncodingException e) {
244 throw new com.sun.star.lang.IllegalArgumentException(e,
245 "Couldn't convert parameter string to UTF-8 string");
249 private static HashMap<String,String> buildParamHashMap(String paramString)
250 throws com.sun.star.lang.IllegalArgumentException {
251 HashMap<String,String> params = new HashMap<String,String>();
253 int pos = 0;
255 while (true) {
256 char c = ',';
257 String aKey = "";
258 String aValue = "";
260 while ((pos < paramString.length())
261 && ((c = paramString.charAt(pos++)) != '=')) {
262 aKey += c;
265 while ((pos < paramString.length())
266 && ((c = paramString.charAt(pos++)) != ',')
267 && c != ';') {
268 aValue += c;
271 if ((aKey.length() > 0) && (aValue.length() > 0)) {
273 if (!isAlphaNumeric(aKey)) {
274 throw new com.sun.star.lang.IllegalArgumentException(
275 "The parameter key '"
276 + aKey
277 + "' may only consist of alpha numeric ASCII characters.");
280 if (!isValidString(aValue, VALUE_CHAR_SET + "%")) {
281 throw new com.sun.star.lang.IllegalArgumentException(
282 "The parameter value for key '" + aKey + "' contains illegal characters.");
285 params.put(aKey, decodeUTF8(aValue));
288 if ((pos >= paramString.length()) || (c != ','))
289 break;
293 return params;
296 private static UnoUrlPart parseUnoUrlPart(String thePart)
297 throws com.sun.star.lang.IllegalArgumentException {
298 String partName;
299 String theParamPart;
300 int index = thePart.indexOf(',');
301 if (index != -1) {
302 partName = thePart.substring(0, index).trim();
303 theParamPart = thePart.substring(index + 1).trim();
304 } else {
305 partName = thePart;
306 theParamPart = "";
309 if (!isAlphaNumeric(partName)) {
310 throw new com.sun.star.lang.IllegalArgumentException(
311 "The part name '"
312 + partName
313 + "' may only consist of alpha numeric ASCII characters.");
316 HashMap<String,String> params = buildParamHashMap(theParamPart);
318 return new UnoUrlPart(theParamPart, partName, params);
321 private static boolean isAlphaNumeric(String s) {
322 return isValidString(s, null);
325 private static boolean isValidString(String identifier, String validCharSet) {
327 int len = identifier.length();
329 for (int i = 0; i < len; i++) {
331 int ch = identifier.charAt(i);
333 boolean isValidChar =
334 ('A' <= ch && ch <= 'Z')
335 || ('a' <= ch && ch <= 'z')
336 || ('0' <= ch && ch <= '9');
338 if (!isValidChar && (validCharSet != null)) {
339 isValidChar = (validCharSet.indexOf(ch) != -1);
342 if (!isValidChar)
343 return false;
346 return true;
350 * Parses the given Uno Url and returns
351 * an in memory object representation.
353 * @param unoUrl The given uno URl as string.
354 * @return Object representation of class UnoUrl.
355 * @throws IllegalArgumentException if Url cannot be parsed.
357 public static UnoUrl parseUnoUrl(String unoUrl)
358 throws com.sun.star.lang.IllegalArgumentException {
360 String url = unoUrl;
362 int index = url.indexOf(':');
363 if (index != -1) {
364 String unoStr = url.substring(0, index).trim();
365 if (!"uno".equals(unoStr)) {
366 throw new com.sun.star.lang.IllegalArgumentException(
367 "Uno Urls must start with 'uno:'. " + FORMAT_ERROR);
371 url = url.substring(index + 1).trim();
373 index = url.indexOf(';');
374 if (index == -1) {
375 throw new com.sun.star.lang.IllegalArgumentException("'"+unoUrl+"' is an invalid Uno Url. " + FORMAT_ERROR);
378 String connection = url.substring(0, index).trim();
379 url = url.substring(index + 1).trim();
381 UnoUrlPart connectionPart = parseUnoUrlPart(connection);
383 index = url.indexOf(';');
384 if (index == -1) {
385 throw new com.sun.star.lang.IllegalArgumentException("'"+unoUrl+"' is an invalid Uno Url. " + FORMAT_ERROR);
388 String protocol = url.substring(0, index).trim();
389 url = url.substring(index + 1).trim();
391 UnoUrlPart protocolPart = parseUnoUrlPart(protocol);
393 String rootOid = url.trim();
394 if (!isValidString(rootOid, OID_CHAR_SET)) {
395 throw new com.sun.star.lang.IllegalArgumentException(
396 "Root OID '"+ rootOid + "' contains illegal characters.");
399 return new UnoUrl(connectionPart, protocolPart, rootOid);