1 /*
   2  * Copyright (c) 1999, 2011, 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.jndi.cosnaming;
  27 
  28 import javax.naming.*;
  29 import javax.naming.directory.*;
  30 import javax.naming.spi.*;
  31 
  32 import org.omg.CosNaming.*;
  33 import org.omg.CosNaming.NamingContextPackage.*;
  34 import org.omg.CORBA.*;
  35 
  36 import com.sun.jndi.toolkit.corba.CorbaUtils;
  37 
  38 /**
  39   * A convenience class to map the COS Naming exceptions to the JNDI exceptions.
  40   * @author Raj Krishnamurthy
  41   */
  42 
  43 public final class ExceptionMapper {
  44     private ExceptionMapper() {} // ensure no instance
  45     private static final boolean debug = false;
  46 
  47     public static final NamingException mapException(Exception e,
  48         CNCtx ctx, NameComponent[] inputName) throws NamingException {
  49         if (e instanceof NamingException) {
  50             return (NamingException)e;
  51         }
  52 
  53         if (e instanceof RuntimeException) {
  54             throw (RuntimeException)e;
  55         }
  56 
  57         NamingException ne;
  58         if (e instanceof NotFound) {
  59             if (ctx.federation) {
  60                 return tryFed((NotFound)e, ctx, inputName);
  61 
  62             } else {
  63                 ne = new NameNotFoundException();
  64             }
  65 
  66         } else if (e instanceof CannotProceed) {
  67 
  68             ne = new CannotProceedException();
  69             NamingContext nc = ((CannotProceed) e).cxt;
  70             NameComponent[] rest = ((CannotProceed) e).rest_of_name;
  71 
  72             // %%% We assume that rest returns *all* unprocessed components.
  73             // Don't' know if that is a good assumption, given
  74             // NotFound doesn't set rest as expected. -RL
  75             if (inputName != null && (inputName.length > rest.length)) {
  76                 NameComponent[] resolvedName =
  77                     new NameComponent[inputName.length - rest.length];
  78                 System.arraycopy(inputName, 0, resolvedName, 0, resolvedName.length);
  79                 // Wrap resolved NamingContext inside a CNCtx
  80                 // Guess that its name (which is relative to ctx)
  81                 // is the part of inputName minus rest_of_name
  82                 ne.setResolvedObj(new CNCtx(ctx._orb, ctx.orbTracker, nc,
  83                                                 ctx._env,
  84                     ctx.makeFullName(resolvedName)));
  85             } else {
  86                 ne.setResolvedObj(ctx);
  87             }
  88 
  89             ne.setRemainingName(CNNameParser.cosNameToName(rest));
  90 
  91         } else if (e instanceof InvalidName) {
  92             ne = new InvalidNameException();
  93         } else if (e instanceof AlreadyBound) {
  94             ne = new NameAlreadyBoundException();
  95         } else if (e instanceof NotEmpty) {
  96             ne = new ContextNotEmptyException();
  97         } else {
  98             ne = new NamingException("Unknown reasons");
  99         }
 100 
 101         ne.setRootCause(e);
 102         return ne;
 103     }
 104 
 105     private static final NamingException tryFed(NotFound e, CNCtx ctx,
 106         NameComponent[] inputName) throws NamingException {
 107         NameComponent[] rest = e.rest_of_name;
 108 
 109         if (debug) {
 110             System.out.println(e.why.value());
 111             System.out.println(rest.length);
 112         }
 113 
 114         // %%% Using 1.2 & 1.3 Sun's tnameserv, 'rest' contains only the first
 115         // component that failed, not *rest* as advertized. This is useless
 116         // because what if you have something like aa/aa/aa/aa/aa.
 117         // If one of those is not found, you get "aa" as 'rest'.
 118         if (rest.length == 1 && inputName != null) {
 119             // Check that we're not talking to 1.2/1.3 Sun tnameserv
 120             NameComponent lastIn = inputName[inputName.length-1];
 121             if (rest[0].id.equals(lastIn.id) &&
 122                 rest[0].kind != null &&
 123                 rest[0].kind.equals(lastIn.kind)) {
 124                 // Might be legit
 125                 ;
 126             } else {
 127                 // Due to 1.2/1.3 bug that always returns single-item 'rest'
 128                 NamingException ne = new NameNotFoundException();
 129                 ne.setRemainingName(CNNameParser.cosNameToName(rest));
 130                 ne.setRootCause(e);
 131                 throw ne;
 132             }
 133         }
 134         // Fixed in 1.4; perform calculations based on correct (1.4) behavior
 135 
 136         // Calculate the components of the name that has been resolved
 137         NameComponent[] resolvedName = null;
 138         int len = 0;
 139         if (inputName != null && (inputName.length >= rest.length)) {
 140 
 141             if (e.why == NotFoundReason.not_context) {
 142                 // First component of rest is found but not a context; keep it
 143                 // as part of resolved name
 144                 len = inputName.length - (rest.length - 1);
 145 
 146                 // Remove resolved component from rest
 147                 if (rest.length == 1) {
 148                     // No more remaining
 149                     rest = null;
 150                 } else {
 151                     NameComponent[] tmp = new NameComponent[rest.length-1];
 152                     System.arraycopy(rest, 1, tmp, 0, tmp.length);
 153                     rest = tmp;
 154                 }
 155             } else {
 156                 len = inputName.length - rest.length;
 157             }
 158 
 159             if (len > 0) {
 160                 resolvedName = new NameComponent[len];
 161                 System.arraycopy(inputName, 0, resolvedName, 0, len);
 162             }
 163         }
 164 
 165         // Create CPE and set common fields
 166         CannotProceedException cpe = new CannotProceedException();
 167         cpe.setRootCause(e);
 168         if (rest != null && rest.length > 0) {
 169             cpe.setRemainingName(CNNameParser.cosNameToName(rest));
 170         }
 171         cpe.setEnvironment(ctx._env);
 172 
 173         if (debug) {
 174             System.out.println("rest of name: " + cpe.getRemainingName());
 175         }
 176 
 177         // Lookup resolved name to get resolved object
 178         final java.lang.Object resolvedObj =
 179             (resolvedName != null) ? ctx.callResolve(resolvedName) : ctx;
 180 
 181         if (resolvedObj instanceof javax.naming.Context) {
 182             // obj is a context and child is not found
 183             // try getting its nns dynamically by constructing
 184             // a Reference containing obj.
 185             RefAddr addr = new RefAddr("nns") {
 186                 public java.lang.Object getContent() {
 187                     return resolvedObj;
 188                 }
 189                 private static final long serialVersionUID =
 190                     669984699392133792L;
 191             };
 192             Reference ref = new Reference("java.lang.Object", addr);
 193 
 194             // Resolved name has trailing slash to indicate nns
 195             CompositeName cname = new CompositeName();
 196             cname.add(""); // add trailing slash
 197 
 198             cpe.setResolvedObj(ref);
 199             cpe.setAltName(cname);
 200             cpe.setAltNameCtx((javax.naming.Context)resolvedObj);
 201 
 202             return cpe;
 203         } else {
 204             // Not a context, use object factory to transform object.
 205 
 206             Name cname = CNNameParser.cosNameToName(resolvedName);
 207             java.lang.Object resolvedObj2 = null;
 208             try {
 209                 // Check whether object factory codebase is trusted
 210                 if (CorbaUtils.isObjectFactoryTrusted(resolvedObj)) {
 211                     resolvedObj2 = NamingManager.getObjectInstance(resolvedObj,
 212                         cname, ctx, ctx._env);
 213                 }
 214             } catch (NamingException ge) {
 215                 throw ge;
 216             } catch (Exception ge) {
 217                 NamingException ne = new NamingException(
 218                     "problem generating object using object factory");
 219                 ne.setRootCause(ge);
 220                 throw ne;
 221             }
 222 
 223             // If a context, continue operation with context
 224             if (resolvedObj2 instanceof javax.naming.Context) {
 225                 cpe.setResolvedObj(resolvedObj2);
 226             } else {
 227                 // Add trailing slash
 228                 cname.add("");
 229                 cpe.setAltName(cname);
 230 
 231                 // Create nns reference
 232                 final java.lang.Object rf2 = resolvedObj2;
 233                 RefAddr addr = new RefAddr("nns") {
 234                     public java.lang.Object getContent() {
 235                         return rf2;
 236                     }
 237                     private static final long serialVersionUID =
 238                         -785132553978269772L;
 239                 };
 240                 Reference ref = new Reference("java.lang.Object", addr);
 241                 cpe.setResolvedObj(ref);
 242                 cpe.setAltNameCtx(ctx);
 243             }
 244             return cpe;
 245         }
 246     }
 247 }