package org.jacorb.util; /* * JacORB - a free Java ORB * * Copyright (C) 1997-2014 Gerald Brose / The JacORB Team. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ import java.io.BufferedReader; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; import org.jacorb.config.JacORBConfiguration; /** * @author Gerald Brose, FU Berlin */ public final class ObjectUtil { //for byte -> hexchar private static final char[] HEX_LOOKUP = new char[]{ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; private ObjectUtil() { // utility class } /** * @return the contents of the resource as a string, or null * if the contents of the resource could not be located using url */ public static String readURL( String url ) throws java.io.IOException { final BufferedReader reader = new BufferedReader(newInputStreamReader(url)); try { return reader.readLine(); } finally { reader.close(); } } private static java.io.InputStreamReader newInputStreamReader(String url) throws MalformedURLException, IOException { String token = "file://"; java.io.InputStreamReader isr = null; if (url.startsWith(token)) { try { isr = new java.io.FileReader(url.substring(token.length())); } catch (Exception e) { System.out.println ("Tried and failed to open file: " + url.substring(token.length())); // no worries, let the URL handle it } } if (isr == null) { java.net.URL urlCopy = new java.net.URL(url); isr = new java.io.InputStreamReader(urlCopy.openStream()); } return isr; } /** * Returns the <code>Class</code> object for the class or interface * with the given string name. This method is a replacement for * <code>Class.forName(String name)</code>. Unlike * <code>Class.forName(String name)</code> (which always uses the * caller's loader or one of its ancestors), <code>classForName</code> * uses a thread-specific loader that has no delegation relationship * with the caller's loader. It attempts the load the desired class * with the thread-specific context class loader and falls back to * <code>Class.forName(String name)</code> only if the context class * loader cannot load the class. * <p> * Loading a class with a loader that is not necessarily an ancestor * of the caller's loader is a crucial thing in many scenarios. As an * example, assume that JacORB was loaded by the boot class loader, * and suppose that some code in JacORB contains a call * <code>Class.forName(someUserClass)</code>. Such usage of * <code>Class.forName</code> effectively forces the user to place * <code>someUserClass</code> in the boot class path. If * <code>classForName(someUserClass)</code> were used instead, the user * class would be loaded by the context class loader, which by default * is set to the system (CLASSPATH) classloader. * <p> * In this simple example above, the default setting of the context class * loader allows classes in the boot classpath to reach classes in the * system classpath. In other scenarios, the context class loader might * be different from the system classloader. Middleware systems like * servlet containers or EJB containers set the context class loader so * that a given thread can reach user-provided classes that are not in * the system classpath. * <p> * For maximum flexibility, <code>classForName</code> should replace * <code>Class.forName(String name)</code> in nearly all cases. * * @param name the fully qualified name of a class * * @return the Class object for that class * * @throws IllegalArgumentException if <code>name</code> is null * @throws ClassNotFoundException if the named class cannot be found * @throws LinkageError if the linkage fails * @throws ExceptionInInitializerError if the class initialization fails */ public static Class<?> classForName(String name) throws ClassNotFoundException, IllegalArgumentException { if (name == null) { throw new IllegalArgumentException("Class name must not be null!"); } if (JacORBConfiguration.useTCCL) { try { // Here we prefer classLoader.loadClass() over the three-argument // form of Class.forName(), as the latter is reported to cause // caching of stale Class instances (due to a buggy cache of // loaded classes). return Thread.currentThread().getContextClassLoader().loadClass(name); } catch (Exception e) { // As a fallback, we prefer Class.forName(name) because it loads // array classes (i.e., it handles arguments like // "[Lsome.class.Name;" or "[[I;", which classLoader.loadClass() // does not handle). return Class.forName(name); } } else { return Class.forName(name); } } public static String bufToString( byte values[], int start, int len) { final StringBuffer result = new StringBuffer(); final StringBuffer chars = new StringBuffer(); for ( int i = start; i < (start + len); i++ ) { if ((i % 16 ) == 0) { result.append( chars.toString() ); result.append( '\n' ); chars.setLength(0); } chars.append( toAscii( values[i] )); result.append( toHex( values[i] )); if ( (i % 4) == 3 ) { chars.append( ' ' ); result.append( ' ' ); } } if ( len % 16 != 0 ) { int pad = 0; int delta_bytes = 16 - (len % 16); //rest of line (no of bytes) //each byte takes two chars plus one ws pad = delta_bytes * 3; //additional whitespaces after four bytes pad += (delta_bytes / 4); // additional whitespace after completed 4 byte block if ((delta_bytes % 4) > 0) { pad += 1; } for ( int i = 0; i < pad; i++ ) { chars.insert( 0, ' ' ); } } result.append( chars.toString()); return result.toString(); } public static void appendHex(StringBuffer buffer, int value) { buffer.append(HEX_LOOKUP[value]); } /** * <code>toHex</code> converts a byte into a readable string. * * @param value a <code>byte</code> value * @return a <code>String</code> value */ public static String toHex(byte value) { final StringBuffer buffer = new StringBuffer(); int upper = (value >> 4) & 0x0F; appendHex(buffer, upper); int lower = value & 0x0F; appendHex(buffer, lower); buffer.append( ' ' ); return buffer.toString(); } public static char toAscii(byte value) { if ( value > (byte) 31 && value < (byte) 127) { return (char) value; } return '.'; } /** * Convenience method to parse an argument vector (typically from * the command line) and sets any arguments of the form "-Dy=x" * as values in a properties object. */ public static java.util.Properties argsToProps(String[] args) { java.util.Properties props = new java.util.Properties(); for( int i = 0; i < args.length; i++ ) { if (args[i].startsWith("-D")) { int idx = args[i].indexOf('='); if (idx < 3 ) { continue; } String key = args[i].substring(2,idx); props.put(key, args[i].substring(idx+1)); } } return props; } public static URL getResource(String name) { if (JacORBConfiguration.useTCCL && Thread.currentThread().getContextClassLoader() != null) { return Thread.currentThread().getContextClassLoader().getResource(name); } return ObjectUtil.class.getResource(name); } }