You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@harmony.apache.org by te...@apache.org on 2006/03/15 15:57:17 UTC
svn commit: r386087 [2/45] - in /incubator/harmony/enhanced/classlib/trunk:
make/ make/patternsets/ modules/jndi/ modules/jndi/META-INF/
modules/jndi/make/ modules/jndi/make/common/ modules/jndi/src/
modules/jndi/src/main/ modules/jndi/src/main/java/ m...
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/hyproperties.xml
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/hyproperties.xml?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/hyproperties.xml (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/make/common/hyproperties.xml Wed Mar 15 06:55:38 2006
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ Copyright 2006 The Apache Software Foundation or its licensors, as applicable.
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+-->
+
+<hy>
+ <jndi location=".">
+ <src>
+ <main>
+ <java location="src/main/java" />
+ <resources location="src/main/resources" />
+ </main>
+ <test>
+ <java location="src/test/java" />
+ <resources location="src/main/resources" />
+ </test>
+ <natives location="src/natives" />
+ </src>
+ <bin>
+ <main location="bin/main" />
+ <test location="bin/test" />
+ </bin>
+ <packaging>
+ </packaging>
+ </jndi>
+
+ <target location="../../deploy" />
+
+ <tests>
+ <reports location="../../build/test_report" />
+ </tests>
+</hy>
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/EnvironmentReader.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/EnvironmentReader.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/EnvironmentReader.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/EnvironmentReader.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,505 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.ibm.jndi;
+
+import java.applet.Applet;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+import java.util.StringTokenizer;
+
+import javax.naming.ConfigurationException;
+import javax.naming.Context;
+import javax.naming.NamingException;
+import javax.naming.ldap.LdapContext;
+
+/**
+ * This is a utility class that reads environment properties.
+ *
+ */
+public final class EnvironmentReader {
+
+ /*
+ * -------------------------------------------------------------------
+ * Constants
+ * -------------------------------------------------------------------
+ */
+
+ // The name of application resource files
+ private static final String APPLICATION_RESOURCE_FILE = "jndi.properties"; //$NON-NLS-1$
+
+ // The name of provider resource file
+ private static final String PROVIDER_RESOURCE_FILE = "jndiprovider.properties"; //$NON-NLS-1$
+
+ /*
+ * -------------------------------------------------------------------
+ * Constructors
+ * -------------------------------------------------------------------
+ */
+
+ // Not allowed to create an instance
+ private EnvironmentReader() {
+ super();
+ }
+
+ /*
+ * Merge additional properties with already read ones.
+ *
+ * @param src - the source containing additional properties
+ * @param dst - the destination to put additional properties
+ * @param valueAddToList - whether to add new values of C-type properties
+ */
+ public static void mergeEnvironment(
+ final Hashtable src,
+ final Hashtable dst,
+ final boolean valueAddToList) {
+
+ Object key = null;
+ String val = null;
+ Enumeration keys = src.keys();
+
+ while (keys.hasMoreElements()) {
+ key = keys.nextElement();
+
+ if (!dst.containsKey(key)) {
+ /*
+ * If this property doesn't exist yet, add it.
+ */
+ dst.put(key, src.get(key));
+ } else if (
+ valueAddToList
+ && (LdapContext.CONTROL_FACTORIES.equals(key)
+ || Context.OBJECT_FACTORIES.equals(key)
+ || Context.STATE_FACTORIES.equals(key)
+ || Context.URL_PKG_PREFIXES.equals(key))) {
+ /*
+ * Otherwise, if this property can contain a list of values, add
+ * the additional values if the flag "valueAddToList" is true.
+ */
+
+ // Read the original value
+ val = (String) dst.get(key);
+ // Values are combined into a single list separated by colons.
+ val = val + ":" + (String) src.get(key); //$NON-NLS-1$
+ // The final value becomes the resulting value of that property
+ dst.put(key, val);
+ } else {
+ /*
+ * Otherwise, ignore the found value.
+ */
+ }
+ }
+ }
+
+ /*
+ * Get the required 7 JNDI properties from JNDI properties source.
+ * This method is designed as package visibility to improve performance
+ * when called by anonymous inner classes.
+ *
+ * @return a hashtable holding the required properties.
+ */
+ static Hashtable filterProperties(final JNDIPropertiesSource source) {
+ final Hashtable filteredProperties = new Hashtable();
+ Object propValue = null;
+
+ propValue = source.getProperty(Context.INITIAL_CONTEXT_FACTORY);
+ if (null != propValue) {
+ filteredProperties.put(Context.INITIAL_CONTEXT_FACTORY, propValue);
+ }
+
+ propValue = source.getProperty(Context.DNS_URL);
+ if (null != propValue) {
+ filteredProperties.put(Context.DNS_URL, propValue);
+ }
+
+ propValue = source.getProperty(Context.PROVIDER_URL);
+ if (null != propValue) {
+ filteredProperties.put(Context.PROVIDER_URL, propValue);
+ }
+
+ propValue = source.getProperty(Context.OBJECT_FACTORIES);
+ if (null != propValue) {
+ filteredProperties.put(Context.OBJECT_FACTORIES, propValue);
+ }
+
+ propValue = source.getProperty(Context.STATE_FACTORIES);
+ if (null != propValue) {
+ filteredProperties.put(Context.STATE_FACTORIES, propValue);
+ }
+
+ propValue = source.getProperty(Context.URL_PKG_PREFIXES);
+ if (null != propValue) {
+ filteredProperties.put(Context.URL_PKG_PREFIXES, propValue);
+ }
+
+ propValue = source.getProperty(LdapContext.CONTROL_FACTORIES);
+ if (null != propValue) {
+ filteredProperties.put(LdapContext.CONTROL_FACTORIES, propValue);
+ }
+
+ return filteredProperties;
+ }
+
+ /*
+ * Read the required 7 JNDI properties from system properties and merge with
+ * existing properties. Note that the values of C-type properties are only
+ * included when no corresponding value is presented in existing properties.
+ *
+ * @param existingProps - existing properties
+ */
+ public static void readSystemProperties(final Hashtable existingProps) {
+ /*
+ * Privileged code is used to access system properties. This is
+ * required if JNDI is run in Applet or other applications which
+ * only have limited permissions to access certain resources.
+ */
+ Hashtable systemProperties =
+ (Hashtable) AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return filterProperties(new SystemPropertiesSource());
+ }
+ });
+ mergeEnvironment(systemProperties, existingProps, false);
+ }
+
+ /*
+ * Read the required 7 JNDI properties from applet parameters and merge with
+ * existing properties. Note that the values of C-type properties are only
+ * included when no corresponding value is presented in existing properties.
+ *
+ * @param applet - the applet object
+ * @param existingProps - existing properties
+ */
+ public static void readAppletParameters(Object applet, Hashtable existingProps) {
+ if (null != applet) {
+ Hashtable appletParameters =
+ filterProperties(new AppletParametersSource((Applet) applet));
+ mergeEnvironment(appletParameters, existingProps, false);
+ }
+ }
+
+ /*
+ * Read multiple resource files from the classpaths given the file name.
+ * This method is designed as package visibility to improve performance
+ * when called by anonymous inner classes.
+ *
+ * @param name - the name of the resource file
+ * @param existingProps - existing properties, cannot be null
+ * @param filter - to filter properties
+ */
+ static Hashtable readMultipleResourceFiles(
+ final String name,
+ final Hashtable existingProps,
+ ClassLoader cl)
+ throws NamingException {
+
+ if (null == cl) {
+ cl = ClassLoader.getSystemClassLoader();
+ }
+
+ Enumeration e = null;
+ try {
+ // Load all resource files
+ e = cl.getResources(name);
+ } catch (IOException ex) {
+ // Unexpected ClassLoader exception
+ ConfigurationException newEx =
+ new ConfigurationException("Failed to load JNDI resource files."); //$NON-NLS-1$
+ newEx.setRootCause(ex);
+ throw newEx;
+ }
+
+ // Read all the loaded properties and merge
+ URL url = null;
+ InputStream is = null;
+ final Properties p = new Properties();
+ while (e.hasMoreElements()) {
+ url = (URL) e.nextElement();
+ try {
+ if (null != (is = url.openStream())) {
+ p.load(is);
+ mergeEnvironment(p, existingProps, true);
+ p.clear();
+ }
+ } catch (IOException ex) {
+ // Can't read this resource file
+ ConfigurationException newEx =
+ new ConfigurationException("Failed to read JNDI resource files."); //$NON-NLS-1$
+ newEx.setRootCause(ex);
+ throw newEx;
+ } finally {
+ try {
+ if (null != is) {
+ is.close();
+ }
+ } catch (IOException ex) {
+ // Ignore closing exception
+ } finally {
+ is = null;
+ }
+ }
+ }
+ return existingProps;
+ }
+
+ /*
+ * Read application/applet resource files.
+ *
+ * @param existingProps - existing properties, cannot be null.
+ */
+ public static Hashtable readApplicationResourceFiles(final Hashtable existingProps)
+ throws NamingException {
+ // Use privileged code to read the application resource files
+ try {
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws NamingException {
+ readMultipleResourceFiles(
+ APPLICATION_RESOURCE_FILE,
+ existingProps,
+ Thread.currentThread().getContextClassLoader());
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ Exception rootCause = e.getException();
+ if (rootCause instanceof NamingException) {
+ throw (NamingException) rootCause;
+ } else if (rootCause instanceof RuntimeException) {
+ throw (RuntimeException) rootCause;
+ } else {
+ // This should not happen.
+ }
+ }
+ return existingProps;
+ }
+
+ /*
+ * Read the properties file "java.home"/lib/jndi.properties.
+ * Pay attention to the privileged code for accessing this external resource
+ * file. This is required if JNDI is run in Applet or other applications
+ * which only have limited permissions to access certain resources.
+ *
+ * @param existingProps - existing properties, cannot be null.
+ */
+ public static Hashtable readLibraryResourceFile(final Hashtable existingProps)
+ throws NamingException {
+ final String sep = System.getProperty("file.separator"); //$NON-NLS-1$
+
+ String resPath = null;
+ // Construct the full filename of "java.home"/lib/jndi.properties
+ resPath = System.getProperty("java.home"); //$NON-NLS-1$
+ if (!resPath.endsWith(sep)) {
+ resPath += sep;
+ }
+ resPath += "lib" + sep + APPLICATION_RESOURCE_FILE; //$NON-NLS-1$
+
+ // Try to read this properties if it exists
+ InputStream is = null;
+ final File resFile = new File(resPath);
+ final Properties p = new Properties();
+ // Use privileged code to determine whether the file exists
+ Boolean resFileExists =
+ (Boolean) AccessController.doPrivileged(new PrivilegedAction() {
+ public Object run() {
+ return new Boolean(resFile.exists());
+ }
+ });
+ if (resFileExists.booleanValue()) {
+ try {
+ // Use privileged code to read the file
+ is =
+ (
+ FileInputStream) AccessController
+ .doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws IOException {
+ InputStream localInputStream = new FileInputStream(resFile);
+ p.load(localInputStream);
+ return localInputStream;
+ }
+ });
+ mergeEnvironment(p, existingProps, true);
+ } catch (PrivilegedActionException e) {
+ // Can't read "java.home"/lib/jndi.properties
+ ConfigurationException newEx =
+ new ConfigurationException("Failed to read JNDI resource files in java home library."); //$NON-NLS-1$
+ newEx.setRootCause(e.getException());
+ throw newEx;
+ } finally {
+ try {
+ if (null != is) {
+ is.close();
+ }
+ } catch (IOException ex) {
+ // Ignore closing exception
+ }
+ }
+ }
+ return existingProps;
+ }
+
+ /*
+ * Read the service provider resource file.
+ *
+ * @param context - the context
+ * @param existingProps - existing properties, cannot be null.
+ */
+ public static Hashtable readProviderResourceFiles(
+ final Context context,
+ final Hashtable existingProps)
+ throws NamingException {
+
+ String factory = context.getClass().getName();
+ String resPath = null;
+ int len = factory.lastIndexOf('.');
+
+ // Construct the full filename of the service provider resource file
+ if (-1 == len) {
+ // Default package
+ resPath = PROVIDER_RESOURCE_FILE;
+ } else {
+ // Replace "." with '/'
+ resPath = factory.substring(0, len + 1);
+ resPath = resPath.replace('.', '/');
+ resPath += PROVIDER_RESOURCE_FILE;
+ }
+
+ // Use privileged code to read the provider resource files
+ try {
+ final String finalResPath = resPath;
+ AccessController.doPrivileged(new PrivilegedExceptionAction() {
+ public Object run() throws NamingException {
+ readMultipleResourceFiles(
+ finalResPath,
+ existingProps,
+ context.getClass().getClassLoader());
+ return null;
+ }
+ });
+ } catch (PrivilegedActionException e) {
+ Exception rootCause = e.getException();
+ if (rootCause instanceof NamingException) {
+ throw (NamingException) rootCause;
+ } else if (rootCause instanceof RuntimeException) {
+ throw (RuntimeException) rootCause;
+ } else {
+ // This should not happen.
+ }
+ }
+ return existingProps;
+ }
+
+ /*
+ * Get the list of the specified factory names from the supplied environment
+ * and the resource provider files of the given Context.
+ *
+ * @param envmt The supplied environment.
+ * @param ctx The Context whose resource provider files will be read.
+ * @param key The name of the factory.
+ * @return The list of the desired factory names.
+ * @throws NamingException If an error occurs when reading the provider
+ * resource files.
+ */
+ public static String[] getFactoryNamesFromEnvironmentAndProviderResource(
+ Hashtable envmt,
+ Context ctx,
+ String key)
+ throws NamingException {
+
+ ArrayList fnames = new ArrayList();
+
+ // collect tokens from envmt with key
+ if (null != envmt) {
+ String str = (String) envmt.get(key);
+ if (null != str) {
+ StringTokenizer st = new StringTokenizer(str, ":"); //$NON-NLS-1$
+ while (st.hasMoreTokens()) {
+ fnames.add(st.nextToken());
+ }
+ }
+ }
+ // collect tokens from ctx's provider resource file
+ if (null != ctx) {
+ Hashtable h = new Hashtable();
+ // read provider resource file from ctx's package
+ EnvironmentReader.readProviderResourceFiles(ctx, h);
+ String str = (String) h.get(key);
+ if (null != str) {
+ StringTokenizer st = new StringTokenizer(str, ":"); //$NON-NLS-1$
+ while (st.hasMoreTokens()) {
+ fnames.add(st.nextToken());
+ }
+ }
+ }
+ // if key is Context.URL_PKG_PREFIXES, append "com.sun.jndi.url" at the end
+ if (Context.URL_PKG_PREFIXES.equals(key)) {
+ fnames.add("com.sun.jndi.url"); //$NON-NLS-1$
+ }
+ // return factory names
+ return (String[]) fnames.toArray(new String[fnames.size()]);
+ }
+
+ /*
+ * Wrapper interface for JNDI properties source.
+ */
+ private interface JNDIPropertiesSource {
+ // Get a JNDI property with the specified name
+ Object getProperty(final String propName);
+ }
+
+ /*
+ * Wrapper class for system properties source.
+ */
+ private static class SystemPropertiesSource implements JNDIPropertiesSource {
+
+ public SystemPropertiesSource() {
+ super();
+ }
+
+ public Object getProperty(final String propName) {
+ return System.getProperty(propName);
+ }
+ }
+
+ /*
+ * Wrapper class for applet parameters source.
+ */
+ private static class AppletParametersSource implements JNDIPropertiesSource {
+
+ private Applet applet;
+
+ public AppletParametersSource(Applet applet) {
+ this.applet = applet;
+ }
+
+ public Object getProperty(final String propName) {
+ return applet.getParameter(propName);
+ }
+ }
+
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/UrlParser.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/UrlParser.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/UrlParser.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/com/ibm/jndi/UrlParser.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,70 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package com.ibm.jndi;
+
+/**
+ * Identifies the simplest URL syntax: <code>{scheme}:{scheme specific part}</code>.
+ *
+ */
+public class UrlParser {
+
+ /*
+ * Prevent instantiate.
+ */
+ private UrlParser() {
+ super();
+ }
+
+ /**
+ * Returns an URL's scheme part, in lower case. If the url is not a valid
+ * URL, null is returned.
+ *
+ * @param url a url string
+ * @return the URL's scheme part, in lower case. If the url is not a
+ * valid URL, null is returned.
+ */
+ public static String getScheme(String url) {
+ if (null == url) {
+ return null;
+ }
+ int colPos = url.indexOf(':');
+ if (colPos < 0) {
+ return null;
+ }
+ String scheme = url.substring(0, colPos);
+ char c;
+ boolean inCharSet;
+ for (int i = 0; i < scheme.length(); i++) {
+ c = scheme.charAt(i);
+ inCharSet =
+ (c >= 'A' && c <= 'Z')
+ || (c >= 'a' && c <= 'z')
+ || (c >= '0' && c <= '9')
+ || c == '+'
+ || c == '.'
+ || c == '-'
+ || c == '_';
+ if (!inCharSet) {
+ return null;
+ }
+ }
+ return scheme;
+ }
+
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/java/applet/Applet.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/java/applet/Applet.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/java/applet/Applet.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/java/applet/Applet.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,22 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/* Just a stub. */
+
+package java.applet;
+
+public class Applet {
+ public String getParameter(String s) { return null; }
+}
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationException.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationException.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,57 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+/**
+ * An <code>AuthenticationException</code> is the
+ * <code>NamingSecurityException</code> used when authentication fails.
+ * <p>
+ * Multithreaded access to an <code>AuthenticationException</code> instance
+ * is only safe when client code locks the object first.</p>
+ *
+ */
+public class AuthenticationException extends NamingSecurityException {
+
+ static final long serialVersionUID = 3678497619904568096L;
+
+ /*
+ * -------------------------------------------------------------------
+ * Constructors
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Constructs an <code>AuthenticationException</code> instance
+ * with all data initialized to null.
+ */
+ public AuthenticationException() {
+ super();
+ }
+
+ /**
+ * Constructs an <code>AuthenticationException</code> instance
+ * using the specified message.
+ *
+ * @param s The detail message for the exception. It may be null.
+ */
+ public AuthenticationException(String s) {
+ super(s);
+ }
+
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationNotSupportedException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationNotSupportedException.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationNotSupportedException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/AuthenticationNotSupportedException.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,58 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+/**
+ * An <code>AuthenticationNotSupportedException</code> is the
+ * <code>NamingSecurityException</code> used
+ * when the authentication required is not available.
+ * <p>
+ * Multithreaded access to an <code>AuthenticationNotSupportedException</code>
+ * instance is only safe when client code locks the object first.</p>
+ *
+ */
+public class AuthenticationNotSupportedException extends NamingSecurityException {
+
+ static final long serialVersionUID = -7149033933259492300L;
+
+ /*
+ * -------------------------------------------------------------------
+ * Constructors
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Constructs an <code>AuthenticationNotSupportedException</code> instance
+ * with all data initialized to null.
+ */
+ public AuthenticationNotSupportedException() {
+ super();
+ }
+
+ /**
+ * Constructs an <code>AuthenticationNotSupportedException</code> instance
+ * using the specified message.
+ *
+ * @param s The detail message for the exception. It may be null.
+ */
+ public AuthenticationNotSupportedException(String s) {
+ super(s);
+ }
+
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/BinaryRefAddr.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/BinaryRefAddr.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/BinaryRefAddr.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/BinaryRefAddr.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,177 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+import java.util.Arrays;
+
+/**
+ * A <code>BinaryRefAddr</code> refers to an address which is represented by a
+ * binary address.
+ *
+ *
+ */
+public class BinaryRefAddr extends RefAddr {
+
+ /*
+ * -------------------------------------------------------------------
+ * Constants
+ * -------------------------------------------------------------------
+ */
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ static final long serialVersionUID = -3415254970957330361L; //J2SE 1.4.2
+
+ /*
+ * -------------------------------------------------------------------
+ * Instance variables
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * The buffer for the binary address itself.
+ *
+ * @serial
+ */
+ private byte[] buf;
+
+ /*
+ * -------------------------------------------------------------------
+ * Constructors
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Constructs a <code>BinaryRefAddr</code> using the specified address type
+ * and the full details of the supplied byte array.
+ *
+ * @param type the address type which cannot be null
+ * @param address the address itself which cannot be null
+ */
+ public BinaryRefAddr(String type, byte[] address) {
+ this(type, address, 0, address.length);
+ }
+
+ /**
+ * Constructs a <code>BinaryRefAddr</code> using the specified address type
+ * and part of the supplied byte array.
+ * The number of bytes to be taken is specified by <code>size</code>.
+ * Additionally these bytes are taken from a starting point specified by
+ * <code>index</code>.
+ *
+ * @param type the address type. It cannot be null.
+ * @param address the address itself. It cannot be null.
+ * @param index the starting point to copy bytes from. It must be
+ * greater than or equal to zero and must be less than or
+ * equal to the size of the byte array.
+ * @param size the number of bytes to copy. It must be greater than or
+ * equal to zero and must be less than or equal to the
+ * size of the byte array less the starting position.
+ * @throws ArrayIndexOutOfBoundsException
+ * If <code>size</code> or <code>index</code> does not meet
+ * the constraints.
+ */
+ public BinaryRefAddr(String type, byte[] address, int index, int size) {
+ super(type);
+ this.buf = new byte[size];
+ System.arraycopy(address, index, this.buf, 0, size);
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods override parent class RefAddr
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Gets the content of this address.
+ *
+ * @return an array of bytes containing the address.
+ * It cannot be null.
+ */
+ public Object getContent() {
+ return buf;
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods override parent class Object
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Returns true if this address is equal to the supplied object
+ * <code>o</code>.
+ * They are considered equal if the address types are equal and the data in
+ * the buffers is of the same length and contains the same bytes.
+ *
+ * @param o the object to compare with
+ * @return true if this address is equal to <code>o</code>,
+ * otherwise false
+ */
+ public boolean equals(Object o) {
+ if (o instanceof BinaryRefAddr) {
+ BinaryRefAddr a = (BinaryRefAddr) o;
+ return this.addrType.equals(a.addrType)
+ && Arrays.equals(this.buf, a.buf);
+ }
+ return false;
+ }
+
+ /**
+ * Returns the hashcode of this address.
+ * The result is the hashcode of the address type added to each byte
+ * from the data buffer.
+ *
+ * @return the hashcode of this address
+ */
+ public int hashCode() {
+ int i = this.addrType.hashCode();
+
+ for (int j = 0; j < this.buf.length; j++) {
+ i += this.buf[j];
+ }
+ return i;
+ }
+
+ /**
+ * Returns the string representation of this address.
+ * The string includes the address type and a maximum of 128 bytes address
+ * content expressed in hexical form.
+ *
+ * @return the string representation of this address
+ */
+ public String toString() {
+ String s =
+ "The type of the address is: " //$NON-NLS-1$
+ + this.addrType
+ + "\nThe content of the address is: "; //$NON-NLS-1$
+ int max = this.buf.length > 128 ? 128 : this.buf.length;
+
+ for (int i = 0; i < max; i++) {
+ s += Integer.toHexString(this.buf[i]) + " "; //$NON-NLS-1$
+ }
+ s = s.substring(0, s.length() - 1) + "\n"; //$NON-NLS-1$
+
+ return s;
+ }
+
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Binding.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Binding.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Binding.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/Binding.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,176 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+/**
+ * Binding extends <code>NameClassPair</code> to associate an object in a
+ * naming service with its name, specified class name and relative flag.
+ * As with <code>NameClassPair</code>, a class name is only specified when
+ * it is necessary to override the real class name of the associated object.
+ * <p>
+ * Multithreaded access to a <code>Binding</code> instance is only safe when
+ * client code locks the object first.</p>
+ *
+ */
+public class Binding extends NameClassPair {
+
+ /*
+ * -------------------------------------------------------------------
+ * Constants
+ * -------------------------------------------------------------------
+ */
+
+ // J2SE 1.4.2
+ private static final long serialVersionUID = 8839217842691845890L;
+
+ /*
+ * -------------------------------------------------------------------
+ * Instance variables
+ * -------------------------------------------------------------------
+ */
+
+ private Object boundObj;
+
+ /*
+ * -------------------------------------------------------------------
+ * Constructors
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Construct a <code>Binding</code> from a name and a class.
+ * The name and class parameters may be null.
+ * Relative flag is true.
+ *
+ * @param name a name
+ * @param obj an object bound with the name
+ */
+ public Binding(String name, Object obj) {
+ this(name, null, obj, true);
+ }
+
+ /**
+ * Construct a <code>Binding</code> from a name, an object and a relative
+ * flag. The name and object parameters may be null.
+ *
+ * @param name a name
+ * @param obj an object bound with the name
+ * @param relative a relative flag
+ */
+ public Binding(String name, Object obj, boolean relative) {
+ this(name, null, obj, relative);
+ }
+
+ /**
+ * Construct a <code>Binding</code> from a name, a class, and an object.
+ * The name, class and object parameters may be null.
+ * Relative flag is true.
+ *
+ * @param name a name
+ * @param className a class name
+ * @param obj an object bound with the name
+ */
+ public Binding(String name, String className, Object obj) {
+ this(name, className, obj, true);
+ }
+
+ /**
+ * Construct a <code>Binding</code> from a name, a class, an object and a
+ * relative flag. The name, class and object parameters may be null.
+ *
+ * @param name a name
+ * @param className a class name
+ * @param obj an object bound with the name
+ * @param relative a relative flag
+ */
+ public Binding(
+ String name,
+ String className,
+ Object obj,
+ boolean relative) {
+ super(name, className, relative);
+ this.boundObj = obj;
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Get the class name of this <code>Binding</code>.
+ * It may have been specified, in which case the class name field is set,
+ * and that is the string returned by this method.
+ * If the class name field has not been specified then the object
+ * associated with this <code>Binding</code> is interrogated to find its
+ * actual class name. If there is no class name field specified and no
+ * associated object then this method returns null.
+ *
+ * @return the class name
+ */
+ public String getClassName() {
+ if (super.getClassName() != null) {
+ return super.getClassName();
+ }
+ if (boundObj != null) {
+ return boundObj.getClass().getName();
+ }
+ return null;
+ }
+
+ /**
+ * Get the object associated with this <code>Binding</code>. May return
+ * null.
+ *
+ * @return the object associated with this <code>Binding</code>.
+ * May return null.
+ */
+ public Object getObject() {
+ return boundObj;
+ }
+
+ /**
+ * Set the object o associated with this <code>Binding</code>. The object
+ * may be null.
+ *
+ * @param object an object
+ */
+ public void setObject(Object object) {
+ this.boundObj = object;
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods override parent class Object
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Provide a string representation of this object. This is the same as for
+ * <code>NameClassPair</code> but with the string representation of the
+ * <code>Binding</code> object appended to the end.
+ *
+ * @return a string representation of this <code>Binding</code>
+ */
+ public String toString() {
+ return super.toString() + ":" + boundObj; //$NON-NLS-1$
+ }
+
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CannotProceedException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CannotProceedException.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CannotProceedException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CannotProceedException.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,238 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+import java.util.Hashtable;
+
+/**
+ * Naming operations throw a <code>CannotProceedException</code> when the
+ * service provider context implementation is resolving a name but reaches a
+ * name component that does not belong to the namespace of the current context.
+ * <p>
+ * The service provider is able to create a <code>CannotProceedException</code>
+ * object and use methods on that object (including baseclass methods) to
+ * provide full details of how far name resolution had progressed.</p>
+ * <p>
+ * Typically, the methods used might include:
+ * <ul>
+ * <li><code>setEnvironment</code> to record the environment from the current
+ * context</li>
+ * <li>
+ * <code>setAltNameCtx</code> to record the current context</li>
+ * <li>
+ * <code>setResolvedObj</code> to record the resolved object for the next
+ * naming system</li>
+ * <li>
+ * <code>setAltName</code> to record the name of the resolved object</li>
+ * <li>
+ * <code>setRemainingName</code> to record the remaining unresolved name</li>
+ * </ul></p>
+ * <p>
+ * If the incomplete naming operation is <code>rename</code>, the service
+ * provider should also use the <code>setRemainingNewName</code> method to
+ * record the unresolved part of the new name.</p>
+ * <p>
+ * The service provider can pass the <code>CannotProceedException</code> as a
+ * parameter to <code>NamingManager</code> methods such as
+ * <code>getContinuationContext</code> to attempt to locate another service
+ * provider for the next naming system. If successful, that service provider
+ * can return a new <code>Context</code> object on which the naming operation
+ * can proceed further. If unsuccessful, the <code>CannotProceedException</code>
+ * can be thrown by the service provider so that the JNDI application can
+ * handle it and take appropriate action.</p>
+ * <p>
+ * Multithreaded access to a single <code>CannotProceedException</code>
+ * instance is only safe when client code uses appropriate synchronization
+ * and locking.</p>
+ *
+ */
+public class CannotProceedException extends NamingException {
+
+ /*
+ * -----------------------------------------
+ * Constants
+ * -----------------------------------------
+ */
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ private final static long serialVersionUID = 1219724816191576813L;
+
+ /*
+ * -------------------------------------------------------------------
+ * Instance variables
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Contains a composite name that is the name of the resolved object which
+ * is relative to the context in <code>altNameCtx</code>. This field may
+ * be null and is initially null. This field should be accessed and
+ * modified using only <code>getAltName</code> and <code>setAltName</code>.
+ */
+ protected Name altName = null;
+
+ /**
+ * Contains the context to which the <code>altName</code> field is relative.
+ * This field may be null and is initially null. A null value implies the
+ * default initial context. This field should be accessed and modified
+ * using only <code>getAltNameCtx</code> and <code>setAltNameCtx</code>.
+ */
+ protected Context altNameCtx = null;
+
+ /**
+ * Contains the environment of the context in which name resolution for the
+ * naming operation could not proceed further. Initially null. Should only
+ * be manipulated using <code>getEnvironment</code>
+ * and <code>setEnvironment methods</code>.
+ */
+ protected Hashtable environment = null;
+
+ /**
+ * Contains a composite name that is the unresolved part of the new name
+ * that was specified in a <code>Context.rename</code> operation and may
+ * be used to continue the <code>rename</code> operation. This field may
+ * be null and is initially null. This field should be accessed and
+ * modified using only <code>getRemainingNewName</code>
+ * and <code>setRemainingNewName</code>.
+ */
+ protected Name remainingNewName = null;
+
+ /*
+ * =======
+ * Constructors
+ * =======
+ */
+
+ /**
+ * Constructs a <code>CannotProceedException</code> object.
+ * All unspecified fields are initialized to null.
+ */
+ public CannotProceedException() {
+ super();
+ }
+
+ /**
+ * Constructs a <code>CannotProceedException</code> object with an
+ * optionally specified <code>String</code> parameter containing a
+ * detailed explanation message. The <code>String</code> parameter may
+ * be null. All unspecified fields are initialized to null.
+ *
+ * @param s The detailed explanation message for the exception.
+ * It may be null.
+ */
+ public CannotProceedException(String s) {
+ super(s);
+ }
+
+ /*
+ * =======
+ * Methods
+ * =======
+ */
+
+ /**
+ * Retrieves the value of the <code>altName</code> field.
+ *
+ * @return the value of the <code>altName</code> field.
+ * @see javax.naming.spi.ObjectFactory#getObjectInstance(Object, Name, Context, Hashtable)
+ */
+ public Name getAltName() {
+ return altName;
+ }
+
+ /**
+ * Retrieves the value of the <code>altNameCtx</code> field.
+ *
+ * @return the value of the <code>altNameCtx</code> field.
+ * @see javax.naming.spi.ObjectFactory#getObjectInstance(Object, Name, Context, Hashtable)
+ */
+ public Context getAltNameCtx() {
+ return altNameCtx;
+ }
+
+ /**
+ * Retrieves the value of the protected field <code>environment</code>
+ * which may be null.
+ *
+ * @return the value of the protected field <code>environment</code>
+ * which may be null.
+ */
+ public Hashtable getEnvironment() {
+ return environment;
+ }
+
+ /**
+ * Retrieves the value of the <code>remainingNewName</code> field.
+ *
+ * @return the value of the <code>remainingNewName</code> field.
+ */
+ public Name getRemainingNewName() {
+ return remainingNewName;
+ }
+
+ /**
+ * Modifies the value of the <code>altName</code> field to the specified
+ * <code>Name</code> parameter which is a composite name and may be null.
+ *
+ * @param name the name to set.
+ */
+ public void setAltName(Name name) {
+ altName = name;
+ }
+
+ /**
+ * Modifies the value of the <code>altNameCtx</code> field to the specified
+ * <code>Context</code> parameter which may be null.
+ *
+ * @param context the new context to set.
+ */
+ public void setAltNameCtx(Context context) {
+ altNameCtx = context;
+ }
+
+ /**
+ * Sets the value of the protected field <code>environment</code> from the
+ * <code>environment</code> parameter which may be null.
+ *
+ * @param hashtable the new environment to set.
+ */
+ public void setEnvironment(Hashtable hashtable) {
+ environment = hashtable;
+ }
+
+ /**
+ * Modifies the value of the <code>remainingNewName</code> field to the
+ * specified parameter which may be null. But otherwise is a composite
+ * name. When needing to specify other names, first convert them into a
+ * composite name with a single component, and then specify that composite
+ * name when invoking this method.
+ * <p>
+ * When a non-null name is specified, a clone of the composite name is
+ * stored in the <code>remainingNewName</code> field that becomes
+ * independent of the specified name.</p>
+ *
+ * @param name the new name to set.
+ */
+ public void setRemainingNewName(Name name) {
+ remainingNewName = (null == name) ? null : (Name) name.clone();
+ }
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CommunicationException.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CommunicationException.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CommunicationException.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CommunicationException.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,55 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+/**
+ * This is the <code>NamingException</code> used when communication with the
+ * naming or directory service fails.
+ * <p>
+ * Multithreaded access to an instance is only safe when client code locks the
+ * object first.</p>
+ *
+ */
+public class CommunicationException extends NamingException {
+
+ /*
+ * This constant is used during deserialization to check the J2SE version
+ * which created the serialized object.
+ */
+ static final long serialVersionUID = 3618507780299986611L; // J2SE 1.4.2
+
+ /**
+ * Constructs a <code>CommunicationException</code> instance with all
+ * data initialized to null.
+ */
+ public CommunicationException() {
+ super();
+ }
+
+ /**
+ * Constructs a <code>CommunicationException</code> instance using the
+ * specified message.
+ *
+ * @param s The detail message for the exception. It may be null.
+ */
+ public CommunicationException(String s) {
+ super(s);
+ }
+
+}
+
+
Added: incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompositeName.java
URL: http://svn.apache.org/viewcvs/incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompositeName.java?rev=386087&view=auto
==============================================================================
--- incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompositeName.java (added)
+++ incubator/harmony/enhanced/classlib/trunk/modules/jndi/src/main/java/javax/naming/CompositeName.java Wed Mar 15 06:55:38 2006
@@ -0,0 +1,652 @@
+/* Copyright 2004 The Apache Software Foundation or its licensors, as applicable
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package javax.naming;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OptionalDataException;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Vector;
+
+/**
+ * A <code>CompositeName</code> represents a name in a naming service which
+ * spans multiple namespaces. For example the name
+ * "www.eclipse.org/index.html" spans the DNS and file system namespaces.
+ * <p>
+ * A <code>CompositeName</code> is a series of string elements. A composite
+ * name has a sequence of zero or more elements delimited by the '/' char.
+ * Each element can be accessed using its position. The first element is at
+ * position 0.</p>
+ * <p>
+ * A <code>CompositeName</code> may be empty. An empty composite name has no
+ * elements. Elements may also be empty.</p>
+ * <p>
+ * <code>CompositeName</code>s are read from left to right unlike
+ * <code>CompoundName</code>s which may have their direction of ordering
+ * specified by properties.</p>
+ * <p>
+ * Special characters are as follows:</p>
+ * <ul>
+ * <li>The separator is /</li>
+ * <li>The escape character is \</li>
+ * <li>Quotes can be used - both single quotes and double quotes are allowed.
+ * This allows you to quote strings which contain chars such as / which are
+ * part of a <code>CompositeName</code> element to avoid them being read as a
+ * separator.</li>
+ * </ul>
+ * <p>
+ * See the examples for further clarification.</p>
+ * <p>
+ * Some Examples:<br />
+ * ==============</p>
+ * <p>
+ * The composite name "www.eclipse.org/index.html" has 2 elements.
+ * "www.eclipse.org" is a name from the DNS namespace.
+ * "index.html" is a name from the file system namespace.</p>
+ * <p>
+ * Another example of a composite name is:
+ * "www.eclipse.org/org/index.html".
+ * This name has 3 elements "www.eclipse.org", "org" and "index.html".
+ * www.eclipse.org is a name from the DNS namespace.
+ * The last 2 elements are each from the file system namespace.</p>
+ * <p>
+ * Some more examples to clarify empty names and elements:</p>
+ * <p>
+ * An empty CompositeName is the name "" and has no elements.</p>
+ * <p>
+ * A CompositeName with just one empty element is the name "/".</p>
+ * <p>
+ * The name "/org/" has 3 elements. The first and last are empty.</p>
+ * <p>
+ * The name "/a" has 2 elements. The first element is empty
+ * and the second element is "a".</p>
+ * <p>
+ * The name "a//a" has 3 elements. The middle element is empty
+ * and the first & third elements are both "a".</p>
+ * <p>
+ * The name "a/'b/a" is invalid as there is no closing quote for the '
+ * character.</p>
+ * <p>
+ * The name "a/'a/b/b" is invalid as there is no closing quote for the '
+ * character.</p>
+ * <p>
+ * The name "a/\"b/a" is interpreted as a/"b/a and is invalid as there is no
+ * closing quote for the embedded escaped " character.</p>
+ * <p>
+ * The name "a/'b/c'/a" has 3 elements. The middle element is b/c.
+ * <p>
+ * The name "a/a'a/b'/b" has 4 elements:
+ * Element 0 is "a".
+ * Element 1 is "a'a".
+ * Element 2 is "b'".
+ * Element 3 is "b".</p>
+ * <p>
+ * Interestingly the name "a/a'a/b/b" is valid and has 4 elements. This is
+ * beacuse the single quote char ' is not a leading quote and is embedded in
+ * an element so is treated as a character.
+ * Element 0 is "a".
+ * Element 1 is "a'a".
+ * Element 2 is "b".
+ * Element 3 is "b".</p>
+ * <p>
+ * The name "\"abcd" gives an <code>InvalidNameException</code> as there is
+ * no closing quote.</p>
+ * <p>
+ * The name "'\"abcd'" gives one element of value "abcd.</p>
+ * <p>
+ * The name "\\abcd" gives one element of value \abcd.</p>
+ * <p>
+ * "" is empty. It has no elements.
+ * "/" has one empty element.
+ * "//" has 2 empty elements.
+ * "/a/" has 3 elements the middle one is set to a.
+ * "///" has 3 empty elements.
+ * "//a/" has 4 elements, the last but one is set to a.</p>
+ *
+ */
+public class CompositeName implements Name {
+
+ /*
+ * -------------------------------------------------------------------
+ * Constants
+ * -------------------------------------------------------------------
+ */
+
+ // J2SE 1.4.2
+ private static final long serialVersionUID = 1667768148915813118L;
+
+ // status used by parse()
+ private static final int OUT_OF_QUOTE = 0;
+ private static final int IN_SINGLE_QUOTE = 1;
+ private static final int IN_DOUBLE_QUOTE = 2;
+ private static final int QUOTE_ENDED = 3;
+
+ /*
+ * -------------------------------------------------------------------
+ * Instance variables
+ * -------------------------------------------------------------------
+ */
+
+ /* a list holding elements */
+ private transient Vector elems;
+
+ /*
+ * -------------------------------------------------------------------
+ * Constructors
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Private copy constructor.
+ *
+ * @param elements a list of name elements
+ */
+ private CompositeName(List elements) {
+ elems = new Vector(elements);
+ }
+
+ /**
+ * Construct a composite name with given elements.
+ *
+ * @param elements an enumeration of name elements
+ */
+ protected CompositeName(Enumeration elements) {
+ elems = new Vector();
+ while (elements.hasMoreElements()) {
+ elems.add(elements.nextElement());
+ }
+ }
+
+ /**
+ * Default constructor, creates an empty name with zero elements.
+ */
+ public CompositeName() {
+ elems = new Vector();
+ }
+
+ /**
+ * This constructor takes the supplied name and breaks it down into its
+ * elements.
+ *
+ * @param name a string containing the full composite name
+ * @throws InvalidNameException if the supplied name is invalid
+ */
+ public CompositeName(String name) throws InvalidNameException {
+ elems = parseName(name);
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods
+ * -------------------------------------------------------------------
+ */
+
+ /*
+ * Parse string name elements. Delimiter is "/".
+ * Escape is "\" and both single quote and double quote are supported.
+ */
+ private static Vector parseName(String name) throws InvalidNameException {
+
+ Vector l = new Vector();
+
+ // special case: all '/', means same number of empty elements
+ if (isAllSlash(name)) {
+ for (int i = 0; i < name.length(); i++) {
+ l.add(""); //$NON-NLS-1$
+ }
+ return l;
+ }
+
+ // general simple case, without escape and quote
+ if (name.indexOf('"') < 0
+ && name.indexOf('\'') < 0
+ && name.indexOf('\\') < 0) {
+ int i = 0, j = 0;
+ while ((j = name.indexOf('/', i)) >= 0) {
+ l.add(name.substring(i, j));
+ i = j + 1;
+ }
+ l.add(name.substring(i));
+ return l;
+ }
+
+ // general complicated case, consider escape and quote
+ char c;
+ char chars[] = name.toCharArray();
+ StringBuffer buf = new StringBuffer();
+ int status = OUT_OF_QUOTE;
+ for (int i = 0; i < chars.length; i++) {
+ c = chars[i];
+
+ // check end quote violation
+ if (status == QUOTE_ENDED) {
+ if (c == '/') {
+ l.add(buf.toString());
+ buf.setLength(0);
+ status = OUT_OF_QUOTE;
+ continue;
+ }
+ throw new InvalidNameException("End quote is not at the end of element"); //$NON-NLS-1$
+ }
+
+ if (c == '\\') {
+ // escape char
+ try {
+ char nc = chars[++i];
+ if (nc == '\\' || nc == '\'' || nc == '"' || nc == '/') {
+ buf.append(nc);
+ } else {
+ buf.append(c);
+ buf.append(nc);
+ }
+ } catch (ArrayIndexOutOfBoundsException e) {
+ throw new InvalidNameException("Escape cannot be at the end of element"); //$NON-NLS-1$
+ }
+ continue;
+ }
+ if (c != '/' && c != '"' && c != '\'') {
+ // normal char
+ buf.append(c);
+ continue;
+ }
+
+ // special char
+ if (status == OUT_OF_QUOTE && c == '/') {
+ l.add(buf.toString());
+ buf.setLength(0);
+ } else if (status == OUT_OF_QUOTE && c == '\'' && buf.length() == 0) {
+ status = IN_SINGLE_QUOTE;
+ } else if (status == OUT_OF_QUOTE && c == '"' && buf.length() == 0) {
+ status = IN_DOUBLE_QUOTE;
+ } else if (status == IN_SINGLE_QUOTE && c == '\'') {
+ status = QUOTE_ENDED;
+ } else if (status == IN_DOUBLE_QUOTE && c == '"') {
+ status = QUOTE_ENDED;
+ } else {
+ buf.append(c);
+ }
+ }
+ l.add(buf.toString());
+
+ // check end status
+ if (status != OUT_OF_QUOTE && status != QUOTE_ENDED) {
+ throw new InvalidNameException("Wrong quote usage."); //$NON-NLS-1$
+ }
+ return l;
+ }
+
+ private static boolean isAllSlash(String name) {
+ for (int i = 0; i < name.length(); i++) {
+ if (name.charAt(i) != '/') {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * Format name elements to its string representation.
+ */
+ private static String formatName(Vector elems) {
+
+ // special case: all empty elements
+ if (isAllEmptyElements(elems)) {
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < elems.size(); i++) {
+ buf.append("/"); //$NON-NLS-1$
+ }
+ return buf.toString();
+ }
+
+ // general case
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < elems.size(); i++) {
+ String elem = (String) elems.get(i);
+ if (i > 0) {
+ buf.append("/"); //$NON-NLS-1$
+ }
+ if (elem.indexOf('/') < 0
+ && elem.indexOf('\\') < 0
+ && elem.indexOf('\'') < 0
+ && elem.indexOf('"') < 0) {
+ buf.append(elem);
+ } else {
+ char chars[] = elem.toCharArray();
+ for (int j = 0; j < chars.length; j++) {
+ char c = chars[j];
+ if (c == '/' || c == '\\' || c == '\'' || c == '"') {
+ buf.append('\\');
+ }
+ buf.append(c);
+ }
+ }
+ }
+ return buf.toString();
+ }
+
+ private static boolean isAllEmptyElements(Vector elems) {
+ for (int i = 0; i < elems.size(); i++) {
+ String elem = (String) elems.get(i);
+ if (elem.length() > 0) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods of interface Name
+ * -------------------------------------------------------------------
+ */
+
+ public Enumeration getAll() {
+ return elems.elements();
+ }
+
+ public String get(int index) {
+ return (String) elems.get(index);
+ }
+
+ public Name getPrefix(int index) {
+ if (index < 0 || index > elems.size()) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ return new CompositeName(elems.subList(0, index));
+ }
+
+ public Name getSuffix(int index) {
+ if (index < 0 || index > elems.size()) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ return new CompositeName(elems.subList(index, elems.size()));
+ }
+
+ public Name addAll(Name name) throws InvalidNameException {
+ if (null == name) {
+ throw new NullPointerException();
+ }
+ if (!(name instanceof CompositeName)) {
+ throw new InvalidNameException("Must be a CompositeName"); //$NON-NLS-1$
+ }
+
+ Enumeration enumeration = name.getAll();
+ while (enumeration.hasMoreElements()) {
+ elems.add(enumeration.nextElement());
+ }
+ return this;
+ }
+
+ public Name addAll(int index, Name name) throws InvalidNameException {
+ if (null == name) {
+ throw new NullPointerException();
+ }
+ if (!(name instanceof CompositeName)) {
+ throw new InvalidNameException("Must be a CompositeName"); //$NON-NLS-1$
+ }
+
+ if (index < 0 || index > elems.size()) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ Enumeration enumeration = name.getAll();
+ while (enumeration.hasMoreElements()) {
+ elems.add(index++, enumeration.nextElement());
+ }
+ return this;
+ }
+
+ public Name add(String element) throws InvalidNameException {
+ elems.add(element);
+ return this;
+ }
+
+ public Name add(int index, String element) throws InvalidNameException {
+ if (index < 0 || index > elems.size()) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ elems.add(index, element);
+ return this;
+ }
+
+ public Object remove(int index) throws InvalidNameException {
+ if (index < 0 || index >= elems.size()) {
+ throw new ArrayIndexOutOfBoundsException();
+ }
+ return elems.remove(index);
+ }
+
+ public int size() {
+ return elems.size();
+ }
+
+ public boolean isEmpty() {
+ return elems.isEmpty();
+ }
+
+ public boolean startsWith(Name name) {
+ if (!(name instanceof CompositeName)) {
+ return false;
+ }
+
+ // check size
+ if (name.size() > elems.size()) {
+ return false;
+ }
+
+ // compare 1 by 1
+ Enumeration enumeration = name.getAll();
+ Object me, he;
+ for (int i = 0; enumeration.hasMoreElements(); i++) {
+ me = elems.get(i);
+ he = enumeration.nextElement();
+ if (!(null == me ? null == he : me.equals(he))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ public boolean endsWith(Name name) {
+ if (!(name instanceof CompositeName)) {
+ return false;
+ }
+
+ // check size
+ if (name.size() > elems.size()) {
+ return false;
+ }
+
+ // compare 1 by 1
+ Enumeration enumeration = name.getAll();
+ Object me, he;
+ for (int i = elems.size() - name.size(); enumeration.hasMoreElements(); i++) {
+ me = elems.get(i);
+ he = enumeration.nextElement();
+ if (!(null == me ? null == he : me.equals(he))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Compare this <code>Name</code> with the one supplied as a parameter.
+ * The elements of the names are compared in the same way as strings are
+ * compared to determine whether this <code>CompositeName</code> is less
+ * than, greater than or equal to the supplied object <code>o</code>.
+ *
+ * @param o the object to compare, cannot be null
+ * @return a negative number means this is less than the supplied object;
+ * a positive number means this is greater than the supplied
+ * object; zero means this CompositeName equals the object as
+ * specified in the description for the equals method of
+ * <code>CompositeName</code>.
+ * @throws ClassCastException when <code>o</code> is not a
+ * <code>CompositeName</code>.
+ */
+ public int compareTo(Object o) {
+ if (o instanceof CompositeName) {
+ CompositeName he = (CompositeName) o;
+ int r;
+ for (int i = 0; i < elems.size() && i < he.elems.size(); i++) {
+ r = ((String) elems.get(i)).compareTo(he.elems.get(i));
+ if (r != 0) {
+ return r;
+ }
+ }
+ if (elems.size() == he.elems.size()) {
+ return 0;
+ } else if (elems.size() < he.elems.size()) {
+ return -1;
+ } else {
+ return 1;
+ }
+ }
+ throw new ClassCastException();
+ }
+
+ /*
+ * -------------------------------------------------------------------
+ * Methods override parent class Object
+ * -------------------------------------------------------------------
+ */
+
+ /**
+ * Create a copy of this composite name, a complete (deep) copy of the object.
+ *
+ * @return a complete (deep) copy of the object.
+ */
+ public Object clone() {
+ // Object.clone()
+ CompositeName copy = null;
+ try {
+ copy = (CompositeName) super.clone();
+ } catch (CloneNotSupportedException e) {
+ // should never happen
+ throw new InternalError(
+ "Failed to clone object of " //$NON-NLS-1$
+ + this.getClass().getName()
+ + " class."); //$NON-NLS-1$
+ }
+
+ // replicate fields
+ copy.elems = new Vector(elems);
+ return copy;
+ }
+
+ /**
+ * Returns the string representation of this <code>CompositeName</code>.
+ * This is generated by concatenating the elements together with the '/'
+ * char added as the separator between each of them. It may be necessary
+ * to add quotes and escape chars to preserve the meaning. The resulting
+ * string should produce an equivalent <code>CompositeName</code> when
+ * used to create a new instance.
+ *
+ * @return the string representation of this composite name.
+ */
+ public String toString() {
+ return formatName(elems);
+ }
+
+ /**
+ * Check if this <code>Name</code> is equal to the supplied object.
+ *
+ * @param o the <code>CompositeName</code> to compare - can be null but
+ * then returns false.
+ * @return true if they have the same number of elements all of
+ * which are equal. false if they are not equal.
+ */
+ public boolean equals(Object o) {
+ // check type
+ if (!(o instanceof CompositeName)) {
+ return false;
+ }
+
+ // check size
+ Name name = (Name) o;
+ if (elems.size() != name.size()) {
+ return false;
+ }
+
+ // compare 1 by 1
+ Enumeration enumeration = name.getAll();
+ Object me, he;
+ for (int i = 0; enumeration.hasMoreElements(); i++) {
+ me = elems.get(i);
+ he = enumeration.nextElement();
+ if (!(null == me ? null == he : me.equals(he))) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Calculate the hashcode of this <code>CompositeName</code> by summing
+ * the hashcodes of all of its elements.
+ *
+ * @return the hashcode of this object.
+ */
+ public int hashCode() {
+ int sum = 0;
+ for (int i = 0; i < elems.size(); i++) {
+ sum += elems.get(i).hashCode();
+ }
+ return sum;
+ }
+
+ /*
+ * Writes a serialized representation of the CompositeName. It starts with
+ * an int which is the number of elements in the name, and is followed by a
+ * String for each element.
+ *
+ * @param oos
+ * @throws java.io.IOException if an error is encountered writing to the stream.
+ */
+ private void writeObject(ObjectOutputStream oos) throws IOException {
+ oos.defaultWriteObject();
+
+ oos.writeInt(elems.size());
+ for (Iterator iter = elems.iterator(); iter.hasNext();) {
+ oos.writeObject(iter.next());
+ }
+ }
+
+ /*
+ * Recreate a CompositeName from the data in the supplied stream.
+ *
+ * @param ois
+ * @throws java.io.IOException if an error is encountered reading from the stream.
+ * @throws ClassNotFoundException.
+ */
+ private void readObject(ObjectInputStream ois)
+ throws OptionalDataException, ClassNotFoundException, IOException {
+ ois.defaultReadObject();
+
+ int size = ois.readInt();
+ elems = new Vector();
+ for (int i = 0; i < size; i++) {
+ elems.add(ois.readObject());
+ }
+ }
+
+}
+
+