DataCollectorBase.java revision 608:7e06bf1dcb09
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
26package com.sun.corba.se.impl.orb ;
27
28import com.sun.corba.se.impl.orbutil.GetPropertyAction ;
29
30import java.security.PrivilegedAction ;
31import java.security.AccessController ;
32
33import java.applet.Applet ;
34
35import java.util.Properties ;
36import java.util.Vector ;
37import java.util.Set ;
38import java.util.HashSet ;
39import java.util.Enumeration ;
40import java.util.Iterator ;
41import java.util.StringTokenizer ;
42
43import java.net.URL ;
44
45import java.security.AccessController ;
46
47import java.io.File ;
48import java.io.FileInputStream ;
49
50import com.sun.corba.se.spi.orb.DataCollector ;
51import com.sun.corba.se.spi.orb.PropertyParser ;
52
53import com.sun.corba.se.impl.orbutil.ORBConstants ;
54import com.sun.corba.se.impl.orbutil.ORBUtility;
55
56public 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
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
95    public boolean initialHostIsLocal()
96    {
97        checkSetParserCalled() ;
98        return localHostName.equals( resultProps.getProperty(
99            ORBConstants.INITIAL_HOST_PROPERTY ) ) ;
100    }
101
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
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
128    public abstract boolean isApplet() ;
129
130//////////////////////////////////////////////////////////
131// Implementation methods needed in subclasses
132//////////////////////////////////////////////////////////
133
134    protected abstract void collect() ;
135
136//////////////////////////////////////////////////////////
137// methods for use by subclasses
138//////////////////////////////////////////////////////////
139
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
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
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
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
252    protected void findPropertiesFromFile()
253    {
254        final Properties fileProps = getFileProperties() ;
255        if (fileProps==null)
256            return ;
257
258        doProperties( fileProps ) ;
259    }
260
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.
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.
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
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).
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.
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
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    //
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
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.
470abstract class PropertyCallback
471{
472    abstract public String get(String name);
473}
474