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.toolkit.ctx; 27 28 import javax.naming.*; 29 import javax.naming.spi.ResolveResult; 30 import java.util.Hashtable; 31 32 /** 33 * This class contains information required to continue 34 * the method (place where it left off, and remaining name to 35 * continue). 36 * 37 * @author Rosanna Lee 38 */ 39 40 public class Continuation extends ResolveResult { 41 /** 42 * The name that we started out with. It is initialized by the constructor 43 * and used to calculate to "resolved name" in NamingException in 44 * fillInException(). 45 * %%% Note that this approach does not always do the calculation 46 * correctly with respect to absence or presence of the trailing slash 47 * for resolved name. 48 */ 49 protected Name starter; 50 51 /** 52 * Whether links were encountered. 53 */ 54 protected Object followingLink = null; 55 56 /** 57 * The environment used by the caller. Initialized by constructor and 58 * used when filling out a CannotProceedException. 59 */ 60 protected Hashtable environment = null; 61 62 /** 63 * Indicates whether the Continuation instance indicates that the operation 64 * should be continued using the data in the Continuation. 65 * Typically, this is only false if an error has been encountered or if 66 * the operation has succeeded. 67 */ 68 protected boolean continuing = false; 69 70 /** 71 * The last resolved context. Used to set the "AltNameCtx" in a 72 * CannotProceedException. 73 */ 74 protected Context resolvedContext = null; 75 76 /** 77 * The resolved name relative to resolvedContext. Used to set the 78 * "AltName" in a CannotProceedException. 79 */ 80 protected Name relativeResolvedName = null; 81 82 /** 83 * Constructs a new instance of Continuation. 84 * Used as dummy for contexts that do not do federation (e.g. for schema ops) 85 */ 86 public Continuation() { 87 } 88 89 /** 90 * Constructs a new instance of Continuation. 91 * @param top The name of the object that is to be resolved/operated upon. 92 * This becomes the Continuation's 'starter' and is used to 93 * calculate the "resolved name" when filling in a NamingException. 94 * @param environment The environment used by the caller. It is used 95 * when setting the "environment" of a CannotProceedException. 96 */ 97 public Continuation(Name top, Hashtable environment) { 98 super(); 99 starter = top; 100 this.environment = environment; 101 } 102 103 /** 104 * Determines whether this Continuation contains data that should be 105 * used to continue the operation. 106 * 107 * @return true if operation should continue; false if operation has 108 * completed (successfully or unsuccessfully). 109 */ 110 public boolean isContinue() { 111 return continuing; 112 } 113 114 /** 115 * Sets this Continuation to indicate successful completion. 116 * Subsequent calls to isContinue() will return false. 117 * This method is different from the setError() methods only from 118 * the standpoint that this method does not set any of the other 119 * fields such as resolved object or resolved context. This is because 120 * this method is typically called when the context recognizes that 121 * the operation has successfully completed and that the continuation 122 * already contains the appropriately set fields. 123 * @see setError 124 * @see setErrorNNS 125 */ 126 public void setSuccess() { 127 continuing = false; 128 } 129 130 /** 131 * Fills in an exception's fields using data from this Continuation. 132 * The resolved name is set by subtracting remainingName from starter. 133 * %%% This might not not always produce the correct answer wrt trailing "/". 134 * If the exception is a CannotProceedException, its environment, 135 * altName, and altNameCtx fields are set using this continuation's 136 * environment, relativeResolvedName, and resolvedContext. 137 * 138 * @param e The non-null naming exception to fill. 139 * @return The non-null naming exception with its fields set using 140 * data from this Continuation. 141 */ 142 public NamingException fillInException(NamingException e) { 143 e.setRemainingName(remainingName); 144 e.setResolvedObj(resolvedObj); 145 146 if (starter == null || starter.isEmpty()) 147 e.setResolvedName(null); 148 else if (remainingName == null) 149 e.setResolvedName(starter); 150 else 151 e.setResolvedName( 152 starter.getPrefix(starter.size() - 153 remainingName.size())); 154 155 if ((e instanceof CannotProceedException)) { 156 CannotProceedException cpe = (CannotProceedException)e; 157 Hashtable env = (environment == null ? 158 new Hashtable(11) : (Hashtable)environment.clone()); 159 cpe.setEnvironment(env); 160 cpe.setAltNameCtx(resolvedContext); 161 cpe.setAltName(relativeResolvedName); 162 } 163 164 return e; 165 } 166 167 /** 168 * Sets this Continuation to indicated that an error has occurred, 169 * and that the remaining name is rename + "/". 170 * 171 * This method is typically called by _nns methods that have been 172 * given a name to process. It might process part of that name but 173 * encountered some error. Consequenetly, it would call setErrorNNS() 174 * with the remaining name. Since the _nns method was expected to 175 * operate upon the "nns" of the original name, the remaining name 176 * must include the "nns". That's why this method adds a trailing "/". 177 *<p> 178 * After this method is called, isContinuing() returns false. 179 * 180 * @param resObj The possibly null object that was resolved to. 181 * @param remain The non-null remaining name. 182 */ 183 public void setErrorNNS(Object resObj, Name remain) { 184 Name nm = (Name)(remain.clone()); 185 try { 186 nm.add(""); 187 } catch (InvalidNameException e) { 188 // ignore; can't happen for composite name 189 } 190 setErrorAux(resObj, nm); 191 } 192 193 /** 194 * Form that accepts a String name instead of a Name name. 195 196 * @param resObj The possibly null object that was resolved to. 197 * @param remain The possibly String remaining name. 198 * 199 * @see #setErrorNNS(java.lang.Object, javax.naming.Name) 200 */ 201 public void setErrorNNS(Object resObj, String remain) { 202 CompositeName rname = new CompositeName(); 203 try { 204 if (remain != null && !remain.equals("")) 205 rname.add(remain); 206 207 rname.add(""); 208 } catch (InvalidNameException e) { 209 // ignore, can't happen for composite name 210 } 211 setErrorAux(resObj, rname); 212 } 213 214 /** 215 * Sets this Continuation to indicated that an error has occurred 216 * and supply resolved information. 217 * 218 * This method is typically called by methods that have been 219 * given a name to process. It might process part of that name but 220 * encountered some error. Consequenetly, it would call setError() 221 * with the resolved object and the remaining name. 222 *<p> 223 * After this method is called, isContinuing() returns false. 224 * 225 * @param resObj The possibly null object that was resolved to. 226 * @param remain The possibly null remaining name. 227 */ 228 public void setError(Object resObj, Name remain) { 229 if (remain != null) 230 remainingName = (Name)(remain.clone()); 231 else 232 remainingName = null; 233 234 setErrorAux(resObj, remainingName); 235 } 236 237 238 /** 239 * Form that accepts a String name instead of a Name name. 240 241 * @param resObj The possibly null object that was resolved to. 242 * @param remain The possibly String remaining name. 243 * 244 * @see #setError(java.lang.Object, javax.naming.Name) 245 */ 246 public void setError(Object resObj, String remain) { 247 CompositeName rname = new CompositeName(); 248 if (remain != null && !remain.equals("")) { 249 try { 250 rname.add(remain); 251 } catch (InvalidNameException e) { 252 // ignore; can't happen for composite name 253 } 254 } 255 setErrorAux(resObj, rname); 256 } 257 258 private void setErrorAux(Object resObj, Name rname) { 259 remainingName = rname; 260 resolvedObj = resObj; 261 continuing = false; 262 } 263 264 private void setContinueAux(Object resObj, 265 Name relResName, Context currCtx, Name remain) { 266 if (resObj instanceof LinkRef) { 267 setContinueLink(resObj, relResName, currCtx, remain); 268 } else { 269 remainingName = remain; 270 resolvedObj = resObj; 271 272 relativeResolvedName = relResName; 273 resolvedContext = currCtx; 274 275 continuing = true; 276 } 277 } 278 279 /** 280 * Sets this Continuation with the supplied data, and set remaining name 281 * to be "/". 282 * This method is typically called by _nns methods that have been 283 * given a name to process. It might the name (without the nns) and 284 * continue process of the nns elsewhere. 285 * Consequently, it would call this form of the setContinueNNS(). 286 * This method supplies "/" as the remaining name. 287 *<p> 288 * After this method is called, isContinuing() returns true. 289 * 290 * @param resObj The possibly null resolved object. 291 * @param relResName The non-null resolved name relative to currCtx. 292 * @param currCtx The non-null context from which relResName is to be resolved. 293 */ 294 public void setContinueNNS(Object resObj, Name relResName, Context currCtx) { 295 CompositeName rname = new CompositeName(); 296 297 setContinue(resObj, relResName, currCtx, PartialCompositeContext._NNS_NAME); 298 } 299 300 /** 301 * Overloaded form that accesses String names. 302 * 303 * @param resObj The possibly null resolved object. 304 * @param relResName The non-null resolved name relative to currCtx. 305 * @param currCtx The non-null context from which relResName is to be resolved. 306 * @see #setContinueNNS(java.lang.Object, javax.naming.Name, javax.naming.Context) 307 */ 308 public void setContinueNNS(Object resObj, String relResName, Context currCtx) { 309 CompositeName relname = new CompositeName(); 310 try { 311 relname.add(relResName); 312 } catch (NamingException e) {} 313 314 setContinue(resObj, relname, currCtx, PartialCompositeContext._NNS_NAME); 315 } 316 317 318 /** 319 * Sets this Continuation with the supplied data, and set remaining name 320 * to be the empty name. 321 * This method is typically called by list-style methods 322 * in which the target context implementing list() expects an 323 * empty name. For example when c_list() is given a non-empty name to 324 * process, it would resolve that name, and then call setContinue() 325 * with the resolved object so that the target context to be listed 326 * would be called with the empty name (i.e. list the target context itself). 327 *<p> 328 * After this method is called, isContinuing() returns true. 329 * 330 * @param resObj The possibly null resolved object. 331 * @param relResName The non-null resolved name relative to currCtx. 332 * @param currCtx The non-null context from which relResName is to be resolved. 333 */ 334 public void setContinue(Object obj, Name relResName, Context currCtx) { 335 setContinueAux(obj, relResName, currCtx, 336 (Name)PartialCompositeContext._EMPTY_NAME.clone()); 337 } 338 339 /** 340 * Sets this Continuation with the supplied data. 341 342 * This method is typically called by a method that has been asked 343 * to operate on a name. The method resolves part of the name 344 * (relResName) to obj and sets the unprocessed part to rename. 345 * It calls setContinue() so that the operation can be continued 346 * using this data. 347 *<p> 348 * After this method is called, isContinuing() returns true. 349 * 350 * @param resObj The possibly null resolved object. 351 * @param relResName The non-null resolved name relative to currCtx. 352 * @param currCtx The non-null context from which relResName is to be resolved. 353 * @param remain The non-null remaining name. 354 */ 355 public void setContinue(Object obj, Name relResName, Context currCtx, Name remain) { 356 if (remain != null) 357 this.remainingName = (Name)(remain.clone()); 358 else 359 this.remainingName = new CompositeName(); 360 361 setContinueAux(obj, relResName, currCtx, remainingName); 362 } 363 364 /** 365 * String overload. 366 * 367 * @param resObj The possibly null resolved object. 368 * @param relResName The non-null resolved name relative to currCtx. 369 * @param currCtx The non-null context from which relResName is to be resolved. 370 * @param remain The non-null remaining name. 371 * @see #setContinue(java.lang.Object, java.lang.String, javax.naming.Context, java.lang.String) 372 */ 373 public void setContinue(Object obj, String relResName, 374 Context currCtx, String remain) { 375 CompositeName relname = new CompositeName(); 376 if (!relResName.equals("")) { 377 try { 378 relname.add(relResName); 379 } catch (NamingException e){} 380 } 381 382 CompositeName rname = new CompositeName(); 383 if (!remain.equals("")) { 384 try { 385 rname.add(remain); 386 } catch (NamingException e) { 387 } 388 } 389 390 setContinueAux(obj, relname, currCtx, rname); 391 } 392 393 /** 394 * %%% This method is kept only for backward compatibility. Delete when 395 * old implementations updated. 396 * 397 * Replaced by setContinue(obj, relResName, (Context)currCtx); 398 * 399 * @deprecated 400 */ 401 @Deprecated 402 public void setContinue(Object obj, Object currCtx) { 403 setContinue(obj, null, (Context)currCtx); 404 } 405 406 407 /** 408 * Sets this Continuation to process a linkRef. 409 * %%% Not working yet. 410 */ 411 private void setContinueLink(Object linkRef, Name relResName, 412 Context resolvedCtx, Name rname) { 413 this.followingLink = linkRef; 414 415 this.remainingName = rname; 416 this.resolvedObj = resolvedCtx; 417 418 this.relativeResolvedName = PartialCompositeContext._EMPTY_NAME; 419 this.resolvedContext = resolvedCtx; 420 421 this.continuing = true; 422 } 423 424 public String toString() { 425 if (remainingName != null) 426 return starter.toString() + "; remainingName: '" + remainingName + "'"; 427 else 428 return starter.toString(); 429 } 430 431 public String toString(boolean detail) { 432 if (!detail || this.resolvedObj == null) 433 return this.toString(); 434 return this.toString() + "; resolvedObj: " + this.resolvedObj + 435 "; relativeResolvedName: " + relativeResolvedName + 436 "; resolvedContext: " + resolvedContext; 437 } 438 439 private static final long serialVersionUID = 8162530656132624308L; 440 }