KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > mx > util > ObjectNameConverter


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.mx.util;
23
24 import java.util.Hashtable JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import java.util.StringTokenizer JavaDoc;
27
28 import javax.management.MalformedObjectNameException JavaDoc;
29 import javax.management.ObjectName JavaDoc;
30
31 /**
32  * Converts forbidden characters in the key and value of an object name
33  * to valid characters and back.
34  * <br>
35  * Character Conversion Table: (based on RFC 1738 style escapes<br>
36  * '%' => '%25' <br>
37  * '*' => '%2a' <br>
38  * ',' => '%2c' <br>
39  * ':' => '%3a' <br>
40  * '?' => '%3f' <br>
41  * '=' => '%3d' <br>
42  * <br>Thanx to William Hoyle for mention this
43  * <br><b>Attention:</b>When you have a comma in one of your property
44  * value then you have to use a <i>Hashtable</i> to provide the properties
45  * otherwise the property parsing will fail.
46  *
47  * @author <a HREF="mailto:andreas@jboss.org">Andreas Schaefer</a>
48  * @author <a HREF="mailto:william.hoyle@jungledrum.co.nz">William Hoyle</a>
49  * @version $Revision: 37459 $
50  */

51 public class ObjectNameConverter
52 {
53    /**
54     * Parses the given Object Name String representation and
55     * replaces any invalid characters in property keays and values with
56     * valid characters.
57     * </b>Attention:</b> Do not use this method when a property
58     * key or value contain a comma because then the parsing will fail.
59     * Please use the {@link #convert( java.lang.String, java.util.Hashtable )
60     * convert( String, Hashtable )} instead because the properties
61     * are already parsed (by you).
62     *
63     * @param pObjectName String representing an Object Name which must
64     * not contain a comman inside a property value
65     *
66     * @return Created Object Name with the converted keys and values
67     * of the given Object Name
68     *
69     * @throws javax.management.MalformedObjectNameException If the given Object Name
70     * is not correct
71     **/

72    public static ObjectName JavaDoc convert( String JavaDoc pObjectName )
73       throws MalformedObjectNameException JavaDoc
74    {
75       if( pObjectName == null ) {
76          throw new MalformedObjectNameException JavaDoc( "null name" );
77       }
78       
79       // REVIEW, is the following a hack?: It is in the spec for patterns
80
if( pObjectName.length() == 0 ) {
81          pObjectName = "*:*";
82       }
83       
84       int lIndex = pObjectName.indexOf( ":" );
85       if( lIndex < 0 ) {
86          throw new MalformedObjectNameException JavaDoc( "missing domain" );
87       }
88       String JavaDoc lDomain = pObjectName.substring( 0, lIndex );
89       if( ( lIndex + 1 ) < pObjectName.length() ) {
90          return createObjectName(lDomain, pObjectName.substring( lIndex + 1 ));
91       } else {
92          throw new MalformedObjectNameException JavaDoc( "properties missing" );
93       }
94    }
95    
96    /**
97     * Check the keys and values of the properties and convert invalid characters
98     *
99     * @param pDomainName Name of the Domain
100     * @param pProperites Hashtable containing the properties of the Object Name
101     *
102     * @return Created Object Name with the converted keays and values
103     *
104     * @throws javax.management.MalformedObjectNameException If the given Object Name
105     * is not correct
106     **/

107    public static ObjectName JavaDoc convert( String JavaDoc pDomainName, Hashtable JavaDoc pProperties )
108       throws MalformedObjectNameException JavaDoc
109    {
110       if( pDomainName == null ) {
111          throw new MalformedObjectNameException JavaDoc( "missing domain" );
112       }
113       if( pProperties == null || pProperties.size() == 0 ) {
114          throw new MalformedObjectNameException JavaDoc(" null or empty properties" );
115       }
116       return createObjectName(pDomainName, pProperties, false);
117    }
118    
119    /**
120     * Takes the properties from the given Object Name and convert
121     * special characters back
122     *
123     * @param pObjectName Given Object Name
124     *
125     * @return Hashtable with the back converted properties in it
126     * and will contain a "*" as key if the given object
127     * name is a property pattern for queries.
128     **/

129    public static Hashtable JavaDoc getProperties( ObjectName JavaDoc pObjectName )
130    {
131       Hashtable JavaDoc lReturn = reverseProperties( pObjectName.getKeyPropertyList() );
132       if( pObjectName.isPropertyPattern() ) {
133          lReturn.put( "*", "*" );
134       }
135       return lReturn;
136    }
137    
138    /**
139     * Takes the properties from the given Object Name and convert
140     * special characters back
141     *
142     * @param pObjectName Given Object Name
143     *
144     * @return String with the original Object Name String representation and
145     * when a property pattern Object Name for queries it contains a ",*"
146     * at the end.
147     **/

148    public static String JavaDoc getString( ObjectName JavaDoc pObjectName )
149    {
150       String JavaDoc lReturn = pObjectName.getDomain() + ":" + reverseString( pObjectName.getKeyPropertyList() );
151       if( pObjectName.isPropertyPattern() ) {
152          lReturn = lReturn + ",*";
153       }
154       return lReturn;
155    }
156    
157    /**
158     * Encrypt or decrypt the forbidden characters in an Object Name value property
159     *
160     * @param pValue Property Value of the Object Name's property list to be en- or decrypted
161     * @param pEncrypt True if the value must be encrypted otherwise decrypted
162     *
163     * @return A en- or decrypted String according to the conversion table above
164     **/

165    public static String JavaDoc convertCharacters( String JavaDoc pValue, boolean pEncrypt ) {
166       String JavaDoc lReturn = pValue;
167       if( pEncrypt ) {
168          int lIndex = lReturn.indexOf( "%" );
169          while( lIndex >= 0 ) {
170             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
171                       "%25" +
172                       ( ( lIndex + 1 ) < lReturn.length() ? lReturn.substring( lIndex + 1 ) : "" );
173             lIndex = lReturn.indexOf( "%", lIndex + 2 );
174          }
175          lIndex = lReturn.indexOf( "*" );
176          while( lIndex >= 0 ) {
177             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
178                       "%2a" +
179                       ( ( lIndex + 1 ) < lReturn.length() ? lReturn.substring( lIndex + 1 ) : "" );
180             lIndex = lReturn.indexOf( "*" );
181          }
182          lIndex = lReturn.indexOf( ":" );
183          while( lIndex >= 0 ) {
184             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
185                       "%3a" +
186                       ( ( lIndex + 1 ) < lReturn.length() ? lReturn.substring( lIndex + 1 ) : "" );
187             lIndex = lReturn.indexOf( ":" );
188          }
189          lIndex = lReturn.indexOf( "?" );
190          while( lIndex >= 0 ) {
191             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
192                       "%3f" +
193                       ( ( lIndex + 1 ) < lReturn.length() ? lReturn.substring( lIndex + 1 ) : "" );
194             lIndex = lReturn.indexOf( "?" );
195          }
196          lIndex = lReturn.indexOf( "=" );
197          while( lIndex >= 0 ) {
198             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
199                       "%3d" +
200                       ( ( lIndex + 1 ) < lReturn.length() ? lReturn.substring( lIndex + 1 ) : "" );
201             lIndex = lReturn.indexOf( "=" );
202          }
203          lIndex = lReturn.indexOf( "," );
204          while( lIndex >= 0 ) {
205             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
206                       "%2c" +
207                       ( ( lIndex + 1 ) < lReturn.length() ? lReturn.substring( lIndex + 1 ) : "" );
208             lIndex = lReturn.indexOf( "," );
209          }
210       } else {
211          int lIndex = lReturn.indexOf( "%2a" );
212          while( lIndex >= 0 ) {
213             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
214                       "*" +
215                       ( ( lIndex + 3 ) < lReturn.length() ? lReturn.substring( lIndex + 3 ) : "" );
216             lIndex = lReturn.indexOf( "%2a" );
217          }
218          lIndex = lReturn.indexOf( "%3a" );
219          while( lIndex >= 0 ) {
220             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
221                       ":" +
222                       ( ( lIndex + 3 ) < lReturn.length() ? lReturn.substring( lIndex + 3 ) : "" );
223             lIndex = lReturn.indexOf( "%3a" );
224          }
225          lIndex = lReturn.indexOf( "%3f" );
226          while( lIndex >= 0 ) {
227             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
228                       "?" +
229                       ( ( lIndex + 3 ) < lReturn.length() ? lReturn.substring( lIndex + 3 ) : "" );
230             lIndex = lReturn.indexOf( "%3f" );
231          }
232          lIndex = lReturn.indexOf( "%3d" );
233          while( lIndex >= 0 ) {
234             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
235                       "=" +
236                       ( ( lIndex + 3 ) < lReturn.length() ? lReturn.substring( lIndex + 3 ) : "" );
237             lIndex = lReturn.indexOf( "%3d" );
238          }
239          lIndex = lReturn.indexOf( "%2c" );
240          while( lIndex >= 0 ) {
241             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
242                       "," +
243                       ( ( lIndex + 3 ) < lReturn.length() ? lReturn.substring( lIndex + 3 ) : "" );
244             lIndex = lReturn.indexOf( "%2c" );
245          }
246          lIndex = lReturn.indexOf( "%25" );
247          while( lIndex >= 0 ) {
248             lReturn = ( lIndex > 0 ? lReturn.substring( 0, lIndex ) : "" ) +
249                       "%" +
250                       ( ( lIndex + 3 ) < lReturn.length() ? lReturn.substring( lIndex + 3 ) : "" );
251             lIndex = lReturn.indexOf( "%25" );
252          }
253       }
254       return lReturn;
255    }
256    
257    /**
258     * takes the properties string and breaks it up into key/value pairs for
259     * insertion into a newly created hashtable.
260     *
261     * minimal validation is performed so that it doesn't blow up when
262     * constructing the kvp strings.
263     *
264     * checks for duplicate keys
265     *
266     * detects property patterns
267     *
268     */

269    private static ObjectName JavaDoc createObjectName(String JavaDoc domain, String JavaDoc properties) throws MalformedObjectNameException JavaDoc
270    {
271       if (null == properties || properties.length() < 1)
272       {
273          throw new MalformedObjectNameException JavaDoc("null or empty properties");
274       }
275       
276       // The StringTokenizer below hides malformations such as ',,' in the
277
// properties string or ',' as the first or last character.
278
// Rather than asking for tokens and building a state machine I'll
279
// just manually check for those 3 scenarios.
280

281       if (properties.startsWith(",") || properties.endsWith(",") || properties.indexOf(",,") != -1)
282       {
283          throw new MalformedObjectNameException JavaDoc("empty key/value pair in properties string");
284       }
285       
286       Hashtable JavaDoc ptable = new Hashtable JavaDoc();
287       
288       StringTokenizer JavaDoc tokenizer = new StringTokenizer JavaDoc(properties, ",");
289       boolean lPattern = false;
290       while (tokenizer.hasMoreTokens())
291       {
292          String JavaDoc chunk = tokenizer.nextToken();
293          
294          if (chunk.equals("*"))
295          {
296             lPattern = true;
297             continue;
298          }
299          
300          int keylen = chunk.length();
301          int eqpos = chunk.indexOf('=');
302          
303          // test below: as in '=value' or 'key=' so that our substrings don't blow up
304
if (eqpos < 1 || (keylen == eqpos + 1))
305          {
306             throw new MalformedObjectNameException JavaDoc("malformed key/value pair: " + chunk);
307          }
308          
309          String JavaDoc key = chunk.substring(0, eqpos);
310          if (ptable.containsKey(key))
311          {
312             throw new MalformedObjectNameException JavaDoc("duplicate key: " + key);
313          }
314          
315          ptable.put(key, chunk.substring(eqpos + 1, keylen));
316       }
317       
318       return createObjectName(domain, ptable, lPattern);
319    }
320
321    /**
322     * validates incoming properties hashtable
323     *
324     * builds canonical string
325     *
326     * precomputes the hashcode
327     */

328    private static ObjectName JavaDoc createObjectName(String JavaDoc domain, Hashtable JavaDoc properties, boolean pPattern) throws MalformedObjectNameException JavaDoc
329    {
330       if (null == properties || (!pPattern && properties.size() < 1))
331       {
332          throw new MalformedObjectNameException JavaDoc("null or empty properties");
333       }
334       
335       Iterator JavaDoc it = properties.keySet().iterator();
336       Hashtable JavaDoc lReturn = new Hashtable JavaDoc( properties.size() );
337       while (it.hasNext())
338       {
339          String JavaDoc key = null;
340          try
341          {
342             key = (String JavaDoc) it.next();
343          }
344          catch (ClassCastException JavaDoc e)
345          {
346             throw new MalformedObjectNameException JavaDoc("key is not a string");
347          }
348
349          String JavaDoc val = null;
350          try
351          {
352             val = (String JavaDoc) properties.get(key);
353          }
354          catch (ClassCastException JavaDoc e)
355          {
356             throw new MalformedObjectNameException JavaDoc("value is not a string");
357          }
358          
359          // Search for invalid characters and replace them
360
String JavaDoc lKey = convertCharacters( key, true );
361          String JavaDoc lValue = convertCharacters( val, true );
362          
363          lReturn.put( lKey, lValue );
364       }
365       ObjectName JavaDoc result = new ObjectName JavaDoc(domain, lReturn);
366       if (pPattern)
367          return new ObjectName JavaDoc(result.getCanonicalName() + ",*");
368       return result;
369    }
370    
371    private static Hashtable JavaDoc reverseProperties( Hashtable JavaDoc pProperties ) {
372       Hashtable JavaDoc lReturn = new Hashtable JavaDoc( pProperties.size() );
373       Iterator JavaDoc i = pProperties.keySet().iterator();
374       while( i.hasNext() ) {
375          String JavaDoc lKey = (String JavaDoc) i.next();
376          String JavaDoc lValue = (String JavaDoc) pProperties.get( lKey );
377          lKey = convertCharacters( lKey, false );
378          lValue = convertCharacters( lValue, false );
379          lReturn.put( lKey, lValue );
380       }
381       return lReturn;
382    }
383    
384    private static String JavaDoc reverseString( Hashtable JavaDoc pProperties ) {
385       StringBuffer JavaDoc lReturn = new StringBuffer JavaDoc();
386       Iterator JavaDoc i = pProperties.keySet().iterator();
387       while( i.hasNext() ) {
388          String JavaDoc lKey = (String JavaDoc) i.next();
389          String JavaDoc lValue = (String JavaDoc) pProperties.get( lKey );
390          lKey = convertCharacters( lKey, false );
391          lValue = convertCharacters( lValue, false );
392          if( lReturn.length() > 0 ) {
393             lReturn.append( "," );
394          }
395          lReturn.append( lKey );
396          lReturn.append( "=" );
397          lReturn.append( lValue );
398       }
399       return lReturn.toString();
400    }
401 }
402
Popular Tags