1 /*
2  * Copyright (c) 2002, 2004, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.  Oracle designates this
8  * particular file as subject to the "Classpath" exception as provided
9  * by Oracle in the LICENSE file that accompanied this code.
10  *
11  * This code is distributed in the hope that it will be useful, but WITHOUT
12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14  * version 2 for more details (a copy is included in the LICENSE file that
15  * accompanied this code).
16  *
17  * You should have received a copy of the GNU General Public License version
18  * 2 along with this work; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20  *
21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22  * or visit www.oracle.com if you need additional information or have any
23  * questions.
24  */
25 
26 package com.sun.corba.se.impl.orb ;
27 
28 import com.sun.corba.se.impl.orbutil.GetPropertyAction ;
29 
30 import java.security.PrivilegedAction ;
31 import java.security.AccessController ;
32 
33 import java.applet.Applet ;
34 
35 import java.util.Properties ;
36 import java.util.Vector ;
37 import java.util.Set ;
38 import java.util.HashSet ;
39 import java.util.Enumeration ;
40 import java.util.Iterator ;
41 import java.util.StringTokenizer ;
42 
43 import java.net.URL ;
44 
45 import java.security.AccessController ;
46 
47 import java.io.File ;
48 import java.io.FileInputStream ;
49 
50 import com.sun.corba.se.spi.orb.DataCollector ;
51 import com.sun.corba.se.spi.orb.PropertyParser ;
52 
53 import com.sun.corba.se.impl.orbutil.ORBConstants ;
54 import com.sun.corba.se.impl.orbutil.ORBUtility;
55 
56 public abstract class DataCollectorBase implements DataCollector {
57     private PropertyParser parser ;
58     private Set propertyNames ;
59     private Set propertyPrefixes ;
60     private Set URLPropertyNames ;
61     protected String localHostName ;
62     protected String configurationHostName ;
63     private boolean setParserCalled ;
64     private Properties originalProps ;
65     private Properties resultProps ;
66 
DataCollectorBase( Properties props, String localHostName, String configurationHostName )67     public DataCollectorBase( Properties props, String localHostName,
68         String configurationHostName )
69     {
70         // XXX This is fully initialized here.  So do we ever want to
71         // generalize this (or perhaps this is the wrong place for this?)
72         URLPropertyNames = new HashSet() ;
73         URLPropertyNames.add( ORBConstants.INITIAL_SERVICES_PROPERTY ) ;
74 
75         propertyNames = new HashSet() ;
76 
77         // Make sure that we are ready to handle -ORBInitRef.  This is special
78         // due to the need to handle multiple -ORBInitRef args as prefix
79         // parsing.
80         propertyNames.add( ORBConstants.ORB_INIT_REF_PROPERTY ) ;
81 
82         propertyPrefixes = new HashSet() ;
83 
84         this.originalProps = props ;
85         this.localHostName = localHostName ;
86         this.configurationHostName = configurationHostName ;
87         setParserCalled = false ;
88         resultProps = new Properties() ;
89     }
90 
91 //////////////////////////////////////////////////////////
92 // Public interface defined in DataCollector
93 //////////////////////////////////////////////////////////
94 
initialHostIsLocal()95     public boolean initialHostIsLocal()
96     {
97         checkSetParserCalled() ;
98         return localHostName.equals( resultProps.getProperty(
99             ORBConstants.INITIAL_HOST_PROPERTY ) ) ;
100     }
101 
setParser( PropertyParser parser )102     public void setParser( PropertyParser parser )
103     {
104         Iterator iter = parser.iterator() ;
105         while (iter.hasNext()) {
106             ParserAction pa = (ParserAction)(iter.next()) ;
107             if (pa.isPrefix())
108                 propertyPrefixes.add( pa.getPropertyName() ) ;
109             else
110                 propertyNames.add( pa.getPropertyName() ) ;
111         }
112 
113         collect() ;
114         setParserCalled = true ;
115     }
116 
getProperties()117     public Properties getProperties()
118     {
119         checkSetParserCalled() ;
120         return resultProps ;
121     }
122 
123 //////////////////////////////////////////////////////////
124 // public interface from DataCollector that must be defined
125 // in subclasses
126 //////////////////////////////////////////////////////////
127 
isApplet()128     public abstract boolean isApplet() ;
129 
130 //////////////////////////////////////////////////////////
131 // Implementation methods needed in subclasses
132 //////////////////////////////////////////////////////////
133 
collect()134     protected abstract void collect() ;
135 
136 //////////////////////////////////////////////////////////
137 // methods for use by subclasses
138 //////////////////////////////////////////////////////////
139 
checkPropertyDefaults()140     protected void checkPropertyDefaults()
141     {
142         String host =
143             resultProps.getProperty( ORBConstants.INITIAL_HOST_PROPERTY ) ;
144 
145         if ((host == null) || (host.equals("")))
146             setProperty( ORBConstants.INITIAL_HOST_PROPERTY,
147                 configurationHostName );
148 
149         String serverHost =
150             resultProps.getProperty( ORBConstants.SERVER_HOST_PROPERTY ) ;
151 
152         if (serverHost == null ||
153             serverHost.equals("") ||
154             serverHost.equals("0.0.0.0") ||
155             serverHost.equals("::") ||
156             serverHost.toLowerCase().equals("::ffff:0.0.0.0"))
157         {
158             setProperty(ORBConstants.SERVER_HOST_PROPERTY,
159                         localHostName);
160             setProperty(ORBConstants.LISTEN_ON_ALL_INTERFACES,
161                         ORBConstants.LISTEN_ON_ALL_INTERFACES);
162         }
163     }
164 
findPropertiesFromArgs( String[] params )165     protected void findPropertiesFromArgs( String[] params )
166     {
167         if (params == null)
168             return;
169 
170         // All command-line args are of the form "-ORBkey value".
171         // The key is mapped to <prefix>.ORBkey.
172 
173         String name ;
174         String value ;
175 
176         for ( int i=0; i<params.length; i++ ) {
177             value = null ;
178             name = null ;
179 
180             if ( params[i] != null && params[i].startsWith("-ORB") ) {
181                 String argName = params[i].substring( 1 ) ;
182                 name = findMatchingPropertyName( propertyNames, argName ) ;
183 
184                 if (name != null)
185                     if ( i+1 < params.length && params[i+1] != null ) {
186                         value = params[++i];
187                     }
188             }
189 
190             if (value != null) {
191                 setProperty( name, value ) ;
192             }
193         }
194     }
195 
findPropertiesFromApplet( final Applet app )196     protected void findPropertiesFromApplet( final Applet app )
197     {
198         // Cannot use propertyPrefixes here, since there is no
199         // way to fetch properties by prefix from an Applet.
200         if (app == null)
201             return;
202 
203         PropertyCallback callback = new PropertyCallback() {
204             public String get(String name) {
205                 return app.getParameter(name);
206             }
207         } ;
208 
209         findPropertiesByName( propertyNames.iterator(), callback ) ;
210 
211         // Special Case:
212         //
213         // Convert any applet parameter relative URLs to an
214         // absolute URL based on the Document Root. This is so HTML
215         // URLs can be kept relative which is sometimes useful for
216         // managing the Document Root layout.
217         PropertyCallback URLCallback = new PropertyCallback() {
218             public String get( String name ) {
219                 String value = resultProps.getProperty(name);
220                 if (value == null)
221                     return null ;
222 
223                 try {
224                     URL url = new URL( app.getDocumentBase(), value ) ;
225                     return url.toExternalForm() ;
226                 } catch (java.net.MalformedURLException exc) {
227                     // Just preserve the original (malformed) value:
228                     // the error will be handled later.
229                     return value ;
230                 }
231             }
232         } ;
233 
234         findPropertiesByName( URLPropertyNames.iterator(),
235             URLCallback ) ;
236     }
237 
doProperties( final Properties props )238     private void doProperties( final Properties props )
239     {
240         PropertyCallback callback =  new PropertyCallback() {
241             public String get(String name) {
242                 return props.getProperty(name);
243             }
244         } ;
245 
246         findPropertiesByName( propertyNames.iterator(), callback ) ;
247 
248         findPropertiesByPrefix( propertyPrefixes,
249             makeIterator( props.propertyNames()), callback );
250     }
251 
findPropertiesFromFile()252     protected void findPropertiesFromFile()
253     {
254         final Properties fileProps = getFileProperties() ;
255         if (fileProps==null)
256             return ;
257 
258         doProperties( fileProps ) ;
259     }
260 
findPropertiesFromProperties()261     protected void findPropertiesFromProperties()
262     {
263         if (originalProps == null)
264             return;
265 
266         doProperties( originalProps ) ;
267     }
268 
269     //
270     // Map System properties to ORB properties.
271     // Security bug fix 4278205:
272     // Only allow reading of system properties with ORB prefixes.
273     // Previously a malicious subclass was able to read ANY system property.
274     // Note that other prefixes are fine in other contexts; it is only
275     // system properties that should impose a restriction.
findPropertiesFromSystem()276     protected void findPropertiesFromSystem()
277     {
278         Set normalNames = getCORBAPrefixes( propertyNames ) ;
279         Set prefixNames = getCORBAPrefixes( propertyPrefixes ) ;
280 
281         PropertyCallback callback = new PropertyCallback() {
282             public String get(String name) {
283                 return getSystemProperty(name);
284             }
285         } ;
286 
287         findPropertiesByName( normalNames.iterator(), callback ) ;
288 
289         findPropertiesByPrefix( prefixNames,
290             getSystemPropertyNames(), callback ) ;
291     }
292 
293 //////////////////////////////////////////////////////////
294 // internal implementation
295 //////////////////////////////////////////////////////////
296 
297     // Store name, value in resultProps, with special
298     // treatment of ORBInitRef.  All updates to resultProps
299     // must happen through this method.
setProperty( String name, String value )300     private void setProperty( String name, String value )
301     {
302         if( name.equals( ORBConstants.ORB_INIT_REF_PROPERTY ) ) {
303             // Value is <name>=<URL>
304             StringTokenizer st = new StringTokenizer( value, "=" ) ;
305             if (st.countTokens() != 2)
306                 throw new IllegalArgumentException() ;
307 
308             String refName = st.nextToken() ;
309             String refValue = st.nextToken() ;
310 
311             resultProps.setProperty( name + "." + refName, refValue ) ;
312         } else {
313             resultProps.setProperty( name, value ) ;
314         }
315     }
316 
checkSetParserCalled()317     private void checkSetParserCalled()
318     {
319         if (!setParserCalled)
320             throw new IllegalStateException( "setParser not called." ) ;
321     }
322 
323     // For each prefix in prefixes, For each name in propertyNames,
324     // if (prefix is a prefix of name) get value from getProperties and
325     // setProperty (name, value).
findPropertiesByPrefix( Set prefixes, Iterator propertyNames, PropertyCallback getProperty )326     private void findPropertiesByPrefix( Set prefixes,
327         Iterator propertyNames, PropertyCallback getProperty )
328     {
329         while (propertyNames.hasNext()) {
330             String name = (String)(propertyNames.next()) ;
331             Iterator iter = prefixes.iterator() ;
332             while (iter.hasNext()) {
333                 String prefix = (String)(iter.next()) ;
334                 if (name.startsWith( prefix )) {
335                     String value = getProperty.get( name ) ;
336 
337                     // Note: do a put even if value is null since just
338                     // the presence of the property may be significant.
339                     setProperty( name, value ) ;
340                 }
341             }
342         }
343     }
344 
345     // For each prefix in names, get the corresponding property
346     // value from the callback, and store the name/value pair in
347     // the result.
findPropertiesByName( Iterator names, PropertyCallback getProperty )348     private void findPropertiesByName( Iterator names,
349         PropertyCallback getProperty )
350     {
351         while (names.hasNext()) {
352             String name = (String)(names.next()) ;
353             String value = getProperty.get( name ) ;
354             if (value != null)
355                 setProperty( name, value ) ;
356         }
357     }
358 
getSystemProperty(final String name)359     private static String getSystemProperty(final String name)
360     {
361         return (String)AccessController.doPrivileged(
362             new GetPropertyAction(name));
363     }
364 
365     // Map command-line arguments to ORB properties.
366     //
findMatchingPropertyName( Set names, String suffix )367     private String findMatchingPropertyName( Set names,
368         String suffix )
369     {
370         Iterator iter = names.iterator() ;
371         while (iter.hasNext()) {
372             String name = (String)(iter.next()) ;
373             if (name.endsWith( suffix ))
374                 return name ;
375         }
376 
377         return null ;
378     }
379 
makeIterator( final Enumeration enumeration )380     private static Iterator makeIterator( final Enumeration enumeration )
381     {
382         return new Iterator() {
383             public boolean hasNext() { return enumeration.hasMoreElements() ; }
384             public Object next() { return enumeration.nextElement() ; }
385             public void remove() { throw new UnsupportedOperationException() ; }
386         } ;
387     }
388 
389     private static Iterator getSystemPropertyNames()
390     {
391         // This will not throw a SecurityException because this
392         // class was loaded from rt.jar using the bootstrap classloader.
393         Enumeration enumeration = (Enumeration)
394             AccessController.doPrivileged(
395                 new PrivilegedAction() {
396                       public java.lang.Object run() {
397                           return System.getProperties().propertyNames();
398                       }
399                 }
400             );
401 
402         return makeIterator( enumeration ) ;
403     }
404 
405     private void getPropertiesFromFile( Properties props, String fileName )
406     {
407         try {
408             File file = new File( fileName ) ;
409             if (!file.exists())
410                 return ;
411 
412             FileInputStream in = new FileInputStream( file ) ;
413 
414             try {
415                 props.load( in ) ;
416             } finally {
417                 in.close() ;
418             }
419         } catch (Exception exc) {
420             // if (ORBInitDebug)
421                 // dprint( "ORB properties file " + fileName + " not found: " +
422                     // exc) ;
423         }
424     }
425 
426     private Properties getFileProperties()
427     {
428         Properties defaults = new Properties() ;
429 
430         String javaHome = getSystemProperty( "java.home" ) ;
431         String fileName = javaHome + File.separator + "lib" + File.separator +
432             "orb.properties" ;
433 
434         getPropertiesFromFile( defaults, fileName ) ;
435 
436         Properties results = new Properties( defaults ) ;
437 
438         String userHome = getSystemProperty( "user.home" ) ;
439         fileName = userHome + File.separator + "orb.properties" ;
440 
441         getPropertiesFromFile( results, fileName ) ;
442         return results ;
443     }
444 
445     private boolean hasCORBAPrefix( String prefix )
446     {
447         return prefix.startsWith( ORBConstants.ORG_OMG_PREFIX ) ||
448             prefix.startsWith( ORBConstants.SUN_PREFIX ) ||
449             prefix.startsWith( ORBConstants.SUN_LC_PREFIX ) ||
450             prefix.startsWith( ORBConstants.SUN_LC_VERSION_PREFIX ) ;
451     }
452 
453     // Return only those element of prefixes for which hasCORBAPrefix
454     // is true.
455     private Set getCORBAPrefixes( final Set prefixes )
456     {
457         Set result = new HashSet() ;
458         Iterator iter = prefixes.iterator() ;
459         while (iter.hasNext()) {
460             String element = (String)(iter.next()) ;
461             if (hasCORBAPrefix( element ))
462                 result.add( element ) ;
463         }
464 
465         return result ;
466     }
467 }
468 
469 // Used to collect properties from various sources.
470 abstract class PropertyCallback
471 {
472     abstract public String get(String name);
473 }
474