Coverage report

| %line | %branch
--- | --- | ---

org.apache.commons.jelly.JellyContext

51%

83%

1

     /*

2

      * Copyright 2002,2004 The Apache Software Foundation.

3

      *

4

      * Licensed under the Apache License, Version 2.0 (the "License");

5

      * you may not use this file except in compliance with the License.

6

      * You may obtain a copy of the License at

7

      *

8

      *      http://www.apache.org/licenses/LICENSE-2.0

9

      *

10

      * Unless required by applicable law or agreed to in writing, software

11

      * distributed under the License is distributed on an "AS IS" BASIS,

12

      * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.

13

      * See the License for the specific language governing permissions and

14

      * limitations under the License.

15

      */

16

     package org.apache.commons.jelly;

17

18

     import java.io.File;

19

     import java.io.IOException;

20

     import java.io.InputStream;

21

     import java.net.MalformedURLException;

22

     import java.net.URL;

23

     import java.util.Collections;

24

     import java.util.HashMap;

25

     import java.util.Hashtable;

26

     import java.util.Iterator;

27

     import java.util.Map;

28

     import java.util.WeakHashMap;

29

30

     import org.apache.commons.jelly.parser.XMLParser;

31

     import org.apache.commons.jelly.util.ClassLoaderUtils;

32

     import org.apache.commons.logging.Log;

33

     import org.apache.commons.logging.LogFactory;

34

     import org.xml.sax.InputSource;

35

     import org.xml.sax.SAXException;

36

37

     /**

38

       * <p><code>JellyContext</code> represents the Jelly context.</p>

39

       *

40

       * @author <a href="mailto:jstrachan@apache.org">James Strachan</a>

41

       * @version $Revision: 165507 $

42

       */

43

     public class JellyContext {

44

45

         /** The Log to which logging calls will be made. */

46

650

         private static final Log log = LogFactory.getLog(JellyContext.class);

47

48

         /** Default for inheritance of variables **/

49

         private static final boolean DEFAULT_INHERIT = true;

50

51

         /** Default for export of variables **/

52

         private static final boolean DEFAULT_EXPORT = false;

53

54

         /** String used to denote a script can't be parsed */

55

         private static final String BAD_PARSE = "Could not parse Jelly script";

56

57

         /**

58

          * The class loader to use for instantiating application objects.

59

          * If not specified, the context class loader, or the class loader

60

          * used to load this class itself, is used, based on the value of the

61

          * <code>useContextClassLoader</code> variable.

62

          */

63

         protected ClassLoader classLoader;

64

65

         /**

66

          * Do we want to use the Context ClassLoader when loading classes

67

          * for instantiating new objects?  Default is <code>false</code>.

68

          */

69

3445

         protected boolean useContextClassLoader = false;

70

71

         /** The root URL context (where scripts are located from) */

72

         private URL rootURL;

73

74

         /** The current URL context (where relative scripts are located from) */

75

         private URL currentURL;

76

77

         /** Tag libraries found so far */

78

3445

         private Map taglibs = new Hashtable();

79

80

         /** synchronized access to the variables in scope */

81

3445

         private Map variables = new Hashtable();

82

83

         /** The parent context */

84

         private JellyContext parent;

85

86

         /** Do we inherit variables from parent context? */

87

3445

         private boolean inherit = JellyContext.DEFAULT_INHERIT;

88

89

         /** Do we export our variables to parent context? */

90

3445

         private boolean export  = JellyContext.DEFAULT_EXPORT;

91

92

         /** Should we export tag libraries to our parents context */

93

3445

         private boolean exportLibraries = true;

94

95

         /**

96

          * Create a new context with the currentURL set to the rootURL

97

          */

98

2210

         public JellyContext() {

99

2210

             this.currentURL = rootURL;

100

2210

             init();

101

2210

         }

102

103

         /**

104

          * Create a new context with the given rootURL

105

          * @param rootURL the root URL used in resolving absolute resources i.e. those starting with '/'

106

          */

107

         public JellyContext(URL rootURL) {

108

13

             this( rootURL, rootURL );

109

13

         }

110

111

         /**

112

          * Create a new context with the given rootURL and currentURL

113

          * @param rootURL the root URL used in resolving absolute resources i.e. those starting with '/'

114

          * @param currentURL the root URL used in resolving relative resources

115

          */

116

832

         public JellyContext(URL rootURL, URL currentURL) {

117

832

             this.rootURL = rootURL;

118

832

             this.currentURL = currentURL;

119

832

             init();

120

832

         }

121

122

123

         /**

124

          * Create a new context with the given parent context.

125

          * The parent's rootURL and currentURL are set on the child, and the parent's variables are

126

          * available in the child context under the name <code>parentScope</code>.

127

          *

128

          * @param parent the parent context for the newly created context.

129

          */

130

403

         public JellyContext(JellyContext parent) {

131

403

             this.parent = parent;

132

403

             this.rootURL = parent.rootURL;

133

403

             this.currentURL = parent.currentURL;

134

403

             this.variables.put("parentScope", parent.variables);

135

403

             init();

136

403

         }

137

138

         /**

139

          * Create a new context with the given parent context.

140

          * The parent's rootURL are set on the child, and the parent's variables are

141

          * available in the child context under the name <code>parentScope</code>.

142

          *

143

          * @param parentJellyContext the parent context for the newly created context.

144

          * @param currentURL the root URL used in resolving relative resources

145

          */

146

         public JellyContext(JellyContext parentJellyContext, URL currentURL) {

147

0

             this(parentJellyContext);

148

0

             this.currentURL = currentURL;

149

0

         }

150

151

         /**

152

          * Create a new context with the given parent context.

153

          * The parent's variables are available in the child context under the name <code>parentScope</code>.

154

          *

155

          * @param parentJellyContext the parent context for the newly created context.

156

          * @param rootURL the root URL used in resolving absolute resources i.e. those starting with '/'

157

          * @param currentURL the root URL used in resolving relative resources

158

          */

159

         public JellyContext(JellyContext parentJellyContext, URL rootURL, URL currentURL) {

160

0

             this(parentJellyContext, currentURL);

161

0

             this.rootURL = rootURL;

162

0

         }

163

164

         /**

165

          * Initialize the context.

166

          * This includes adding the context to itself under the name <code>context</code> and

167

          * making the System Properties available as <code>systemScope</code>

168

          */

169

         private void init() {

170

3445

             variables.put("context",this);

171

             try {

172

3445

                 variables.put("systemScope", System.getProperties() );

173

0

             } catch (SecurityException e) {

174

0

                 log.debug("security exception accessing system properties", e);

175

3445

             }

176

3445

         }

177

178

         /**

179

          * @return the parent context for this context

180

          */

181

         public JellyContext getParent() {

182

9100

             return parent;

183

         }

184

185

         /**

186

          * @return the scope of the given name, such as the 'parent' scope.

187

          * If Jelly is used in a Servlet situation then 'request', 'session' and 'application' are other names

188

          * for scopes

189

          */

190

         public JellyContext getScope(String name) {

191

0

             if ( "parent".equals( name ) ) {

192

0

                 return getParent();

193

             }

194

0

             return null;

195

         }

196

197

         /**

198

          * Finds the variable value of the given name in this context or in any other parent context.

199

          * If this context does not contain the variable, then its parent is used and then its parent

200

          * and so forth until the context with no parent is found.

201

          *

202

          * @return the value of the variable in this or one of its descendant contexts or null

203

          *  if the variable could not be found.

204

          */

205

         public Object findVariable(String name) {

206

0

             Object answer = variables.get(name);

207

0

             boolean definedHere = answer != null || variables.containsKey(name);

208

209

0

             if (definedHere) return answer;

210

211

0

             if ( answer == null && parent != <span class="keyword">null ) {

212

0

                 answer = parent.findVariable(name);

213

             }

214

             // ### this is a hack - remove this when we have support for pluggable Scopes

215

0

             if ( answer == null ) {

216

0

                 answer = getSystemProperty(name);

217

             }

218

219

0

             if (log.isDebugEnabled()) {

220

0

                 log.debug("findVariable: " + name + " value: " + answer );

221

             }

222

0

             return answer;

223

         }

224

225

226

         /** @return the value of the given variable name */

227

         public Object getVariable(String name) {

228

17576

             Object value = variables.get(name);

229

17576

             boolean definedHere = value != null || variables.containsKey(name);

230

231

17576

             if (definedHere) return value;

232

233

9113

             if ( value == null && isInherit() ) {

234

9061

                 JellyContext parentContext = getParent();

235

9061

                 if (parentContext != null) {

236

416

                     value = parentContext.getVariable( name );

237

                 }

238

             }

239

240

             // ### this is a hack - remove this when we have support for pluggable Scopes

241

9113

             if ( value == null ) {

242

9074

                 value = getSystemProperty(name);

243

             }

244

245

9113

             return value;

246

         }

247

248

         /**

249

          * Get a system property and handle security exceptions

250

          * @param name the name of the property to retrieve

251

          * @return the value of the property, or null if a SecurityException occurs

252

          */

253

         private Object getSystemProperty(String name) {

254

             try {

255

9074

                 return System.getProperty(name);

256

             }

257

0

             catch (SecurityException e) {

258

0

                 log.debug("security exception accessing system properties", e);

259

             }

260

0

             return null;

261

         }

262

263

         /**

264

          * @return the value of the given variable name in the given variable scope

265

          * @param name is the name of the variable

266

          * @param scopeName is the optional scope name such as 'parent'. For servlet environments

267

          * this could be 'application', 'session' or 'request'.

268

          */

269

         public Object getVariable(String name, String scopeName) {

270

0

             JellyContext scope = getScope(scopeName);

271

0

             if ( scope != null ) {

272

0

                 return scope.getVariable(name);

273

             }

274

0

             return null;

275

         }

276

277

278

279

         /** Sets the value of the named variable */

280

         public void setVariable(String name, Object value) {

281

6448

             if ( isExport() ) {

282

39

                 getParent().setVariable( name, value );

283

39

                 return;

284

             }

285

6409

             if (value == null) {

286

52

                 variables.remove(name);

287

52

             }

288

             else {

289

6357

                 variables.put(name, value);

290

             }

291

6409

         }

292

293

         /**

294

          * Sets the value of the given variable name in the given variable scope

295

          * @param name is the name of the variable

296

          * @param scopeName is the optional scope name such as 'parent'. For servlet environments

297

          *  this could be 'application', 'session' or 'request'.

298

          * @param value is the value of the attribute

299

          */

300

         public void setVariable(String name, String scopeName, Object value) {

301

0

             JellyContext scope = getScope(scopeName);

302

0

             if ( scope != null ) {

303

0

                 scope.setVariable(name, value);

304

             }

305

0

         }

306

307

         /** Removes the given variable */

308

         public void removeVariable(String name) {

309

78

             variables.remove(name);

310

78

         }

311

312

         /**

313

          * Removes the given variable in the specified scope.

314

          *

315

          * @param name is the name of the variable

316

          * @param scopeName is the optional scope name such as 'parent'. For servlet environments

317

          *  this could be 'application', 'session' or 'request'.

318

          */

319

         public void removeVariable(String name, String scopeName) {

320

0

             JellyContext scope = getScope(scopeName);

321

0

             if ( scope != null ) {

322

0

                 scope.removeVariable(name);

323

             }

324

0

         }

325

326

         /**

327

          * @return an Iterator over the current variable names in this

328

          * context

329

          */

330

         public Iterator getVariableNames() {

331

0

             return variables.keySet().iterator();

332

         }

333

334

         /**

335

          * @return the Map of variables in this scope

336

          */

337

         public Map getVariables() {

338

0

             return variables;

339

         }

340

341

         /**

342

          * Sets the Map of variables to use

343

          */

344

         public void setVariables(Map variables) {

345

             // I have seen this fail when the passed Map contains a key, value

346

             // pair where the value is null

347

13

             for (Iterator iter = variables.entrySet().iterator(); iter.hasNext();) {

348

0

                 Map.Entry element = (Map.Entry) iter.next();

349

0

                 if (element.getValue() != null) {

350

0

                     this.variables.put(element.getKey(), element.getValue());

351

                 }

352

0

             }

353

             //this.variables.putAll( variables );

354

13

         }

355

356

         /**

357

          * A factory method to create a new child context of the

358

          * current context.

359

          */

360

         public JellyContext newJellyContext(Map newVariables) {

361

             // XXXX: should allow this new context to

362

             // XXXX: inherit parent contexts?

363

             // XXXX: Or at least publish the parent scope

364

             // XXXX: as a Map in this new variable scope?

365

0

             newVariables.put("parentScope", variables);

366

0

             JellyContext answer = createChildContext();

367

0

             answer.setVariables(newVariables);

368

0

             return answer;

369

         }

370

371

         /**

372

          * A factory method to create a new child context of the

373

          * current context.

374

          */

375

         public JellyContext newJellyContext() {

376

156

             return createChildContext();

377

         }

378

379

         /** Clears variables set by Tags.

380

          * @see #clearVariables()

381

           */

382

         public void clear() {

383

0

             clearVariables();

384

0

         }

385

386

         /** Clears variables set by Tags (variables set while running a Jelly script)

387

          * @see #clear()

388

          */

389

         protected void clearVariables() {

390

0

             variables.clear();

391

0

         }

392

393

         /** Registers the given tag library against the given namespace URI.

394

          * This should be called before the parser is used.

395

          */

396

         public void registerTagLibrary(String namespaceURI, TagLibrary taglib) {

397

52

             if (log.isDebugEnabled()) {

398

0

                 log.debug("Registering tag library to: " + namespaceURI + " taglib: " + taglib);

399

             }

400

52

             taglibs.put(namespaceURI, taglib);

401

402

52

             if (isExportLibraries() && parent != null) {

403

0

                 parent.registerTagLibrary( namespaceURI, taglib );

404

             }

405

52

         }

406

407

         /** Registers the given tag library class name against the given namespace URI.

408

          * The class will be loaded via the given ClassLoader

409

          * This should be called before the parser is used.

410

          */

411

         public void registerTagLibrary(

412

             String namespaceURI,

413

             String className) {

414

415

35074

             if (log.isDebugEnabled()) {

416

0

                 log.debug("Registering tag library to: " + namespaceURI + " taglib: " + className);

417

             }

418

35074

             taglibs.put(namespaceURI, className);

419

420

35074

             if (isExportLibraries() && parent != null) {

421

0

                 parent.registerTagLibrary( namespaceURI, className );

422

             }

423

35074

         }

424

425

         public boolean isTagLibraryRegistered(String namespaceURI) {

426

42978

             boolean answer = taglibs.containsKey( namespaceURI );

427

42978

             if (answer) {

428

3952

                 return true;

429

             }

430

39026

             else if ( parent != null ) {

431

3952

                 return parent.isTagLibraryRegistered(namespaceURI);

432

             }

433

             else {

434

35074

                 return false;

435

             }

436

         }

437

438

         /**

439

          * @return the TagLibrary for the given namespace URI or null if one could not be found

440

          */

441

         public TagLibrary getTagLibrary(String namespaceURI) {

442

443

             // use my own mapping first, so that namespaceURIs can

444

             // be redefined inside child contexts...

445

446

20449

             Object answer = taglibs.get(namespaceURI);

447

448

20449

             if ( answer == null && parent != <span class="keyword">null ) {

449

312

                 answer = parent.getTagLibrary( namespaceURI );

450

             }

451

452

20449

             if ( answer instanceof TagLibrary ) {

453

18941

                 return (TagLibrary) answer;

454

             }

455

1508

             else if ( answer instanceof String ) {

456

936

                 String className = (String) answer;

457

936

                 Class theClass = null;

458

                 try {

459

936

                     theClass = getClassLoader().loadClass(className);

460

                 }

461

0

                 catch (ClassNotFoundException e) {

462

0

                     log.error("Could not find the class: " + className, e);

463

936

                 }

464

936

                 if ( theClass != null ) {

465

                     try {

466

936

                         Object object = theClass.newInstance();

467

936

                         if (object instanceof TagLibrary) {

468

936

                             taglibs.put(namespaceURI, object);

469

936

                             return (TagLibrary) object;

470

                         }

471

                         else {

472

0

                             log.error(

473

                                 "The tag library object mapped to: "

474

                                     + namespaceURI

475

                                     + " is not a TagLibrary. Object = "

476

                                     + object);

477

                         }

478

                     }

479

0

                     catch (Exception e) {

480

0

                         log.error(

481

                             "Could not instantiate instance of class: " + className + ". Reason: " + e,

482

                             e);

483

0

                     }

484

                 }

485

             }

486

487

572

             return null;

488

         }

489

490

         /**

491

          * Attempts to parse the script from the given uri using the

492

          * {@link #getResource} method then returns the compiled script.

493

          */

494

         public Script compileScript(String uri) throws JellyException {

495

0

             XMLParser parser = getXMLParser();

496

0

             parser.setContext(this);

497

0

             InputStream in = getResourceAsStream(uri);

498

0

             if (in == null) {

499

0

                 throw new JellyException("Could not find Jelly script: " + uri);

500

             }

501

0

             Script script = null;

502

             try {

503

0

                 script = parser.parse(in);

504

0

             } catch (IOException e) {

505

0

                 throw new JellyException(JellyContext.BAD_PARSE, e);

506

0

             } catch (SAXException e) {

507

0

                 throw new JellyException(JellyContext.BAD_PARSE, e);

508

0

             }

509

510

0

             return script.compile();

511

         }

512

513

         /**

514

          * Attempts to parse the script from the given URL using the

515

          * {@link #getResource} method then returns the compiled script.

516

          */

517

         public Script compileScript(URL url) throws JellyException {

518

0

             XMLParser parser = getXMLParser();

519

0

             parser.setContext(this);

520

521

0

             Script script = null;

522

             try {

523

0

                 script = parser.parse(url.toString());

524

0

             } catch (IOException e) {

525

0

                 throw new JellyException(JellyContext.BAD_PARSE, e);

526

0

             } catch (SAXException e) {

527

0

                 throw new JellyException(JellyContext.BAD_PARSE, e);

528

0

             }

529

530

0

             return script.compile();

531

         }

532

533

         /**

534

          * Attempts to parse the script from the given InputSource using the

535

          * {@link #getResource} method then returns the compiled script.

536

          */

537

         public Script compileScript(InputSource source) throws JellyException {

538

130

             XMLParser parser = getXMLParser();

539

130

             parser.setContext(this);

540

541

130

             Script script = null;

542

             try {

543

130

                 script = parser.parse(source);

544

0

             } catch (IOException e) {

545

0

                 throw new JellyException(JellyContext.BAD_PARSE, e);

546

0

             } catch (SAXException e) {

547

0

                 throw new JellyException(JellyContext.BAD_PARSE, e);

548

130

             }

549

550

130

             return script.compile();

551

         }

552

553

         /**

554

          * @return a thread pooled XMLParser to avoid the startup overhead

555

          * of the XMLParser

556

          */

557

         protected XMLParser getXMLParser() {

558

130

             XMLParser parser = createXMLParser();

559

130

             return parser;

560

         }

561

562

         /**

563

          * Factory method to allow JellyContext implementations to overload how an XMLParser

564

          * is created - such as to overload what the default ExpressionFactory should be.

565

          */

566

         protected XMLParser createXMLParser() {

567

130

             return new XMLParser();

568

         }

569

570

         /**

571

          * Parses the script from the given File then compiles it and runs it.

572

          *

573

          * @return the new child context that was used to run the script

574

          */

575

         public JellyContext runScript(File file, XMLOutput output) throws JellyException {

576

             try {

577

0

                 return runScript(file.toURL(), output, JellyContext.DEFAULT_EXPORT,

578

                     JellyContext.DEFAULT_INHERIT);

579

0

             } catch (MalformedURLException e) {

580

0

                 throw new JellyException(e.toString());

581

             }

582

         }

583

584

         /**

585

          * Parses the script from the given URL then compiles it and runs it.

586

          *

587

          * @return the new child context that was used to run the script

588

          */

589

         public JellyContext runScript(URL url, XMLOutput output) throws JellyException {

590

13

             return runScript(url, output, JellyContext.DEFAULT_EXPORT,

591

                 JellyContext.DEFAULT_INHERIT);

592

         }

593

594

         /**

595

          * Parses the script from the given InputSource then compiles it and runs it.

596

          *

597

          * @return the new child context that was used to run the script

598

          */

599

         public JellyContext runScript(InputSource source, XMLOutput output) throws JellyException {

600

13

             return runScript(source, output, JellyContext.DEFAULT_EXPORT,

601

                 JellyContext.DEFAULT_INHERIT);

602

         }

603

604

         /**

605

          * Parses the script from the given uri using the

606

          * JellyContext.getResource() API then compiles it and runs it.

607

          *

608

          * @return the new child context that was used to run the script

609

          */

610

         public JellyContext runScript(String uri, XMLOutput output) throws JellyException {

611

0

             URL url = null;

612

             try {

613

0

                 url = getResource(uri);

614

0

             } catch (MalformedURLException e) {

615

0

                 throw new JellyException(e.toString());

616

0

             }

617

618

0

             if (url == null) {

619

0

                 throw new JellyException("Could not find Jelly script: " + url);

620

             }

621

0

             return runScript(url, output, JellyContext.DEFAULT_EXPORT,

622

                 JellyContext.DEFAULT_INHERIT);

623

         }

624

625

         /**

626

          * Parses the script from the given uri using the

627

          * JellyContext.getResource() API then compiles it and runs it.

628

          *

629

          * @return the new child context that was used to run the script

630

          */

631

         public JellyContext runScript(String uri, XMLOutput output,

632

                               boolean export, <span class="keyword">boolean inherit) throws JellyException {

633

104

             URL url = null;

634

             try {

635

104

                 url = getResource(uri);

636

0

             } catch (MalformedURLException e) {

637

0

                 throw new JellyException(e.toString());

638

104

             }

639

640

104

             if (url == null) {

641

0

                 throw new JellyException("Could not find Jelly script: " + url);

642

             }

643

644

104

             return runScript(url, output, export, inherit);

645

         }

646

647

         /**

648

          * Parses the script from the given file then compiles it and runs it.

649

          *

650

          * @return the new child context that was used to run the script

651

          */

652

         public JellyContext runScript(File file, XMLOutput output,

653

                               boolean export, <span class="keyword">boolean inherit) throws JellyException {

654

             try {

655

0

                 return runScript(file.toURL(), output, export, inherit);

656

0

             } catch (MalformedURLException e) {

657

0

                 throw new JellyException(e.toString());

658

             }

659

         }

660

661

         /**

662

          * Parses the script from the given URL then compiles it and runs it.

663

          *

664

          * @return the new child context that was used to run the script

665

          */

666

         public JellyContext runScript(URL url, XMLOutput output,

667

                               boolean export, <span class="keyword">boolean inherit) throws JellyException {

668

117

             return runScript(new InputSource(url.toString()), output, export, inherit);

669

         }

670

671

         /**

672

          * Parses the script from the given InputSource then compiles it and runs it.

673

          *

674

          * @return the new child context that was used to run the script

675

          */

676

         public JellyContext runScript(InputSource source, XMLOutput output,

677

                               boolean export, <span class="keyword">boolean inherit) throws JellyException {

678

130

             Script script = compileScript(source);

679

680

130

             URL newJellyContextURL = null;

681

             try {

682

130

                 newJellyContextURL = getJellyContextURL(source);

683

0

             } catch (MalformedURLException e) {

684

0

                 throw new JellyException(e.toString());

685

130

             }

686

687

130

             JellyContext newJellyContext = newJellyContext();

688

130

             newJellyContext.setRootURL( newJellyContextURL );

689

130

             newJellyContext.setCurrentURL( newJellyContextURL );

690

130

             newJellyContext.setExport( export );

691

130

             newJellyContext.setInherit( inherit );

692

693

130

             if ( inherit ) {

694

                 // use the same variable scopes

695

104

                 newJellyContext.variables = this.variables;

696

             }

697

698

130

             if (log.isDebugEnabled() ) {

699

0

                 log.debug( "About to run script: " + source.getSystemId() );

700

0

                 log.debug( "root context URL: " + newJellyContext.rootURL );

701

0

                 log.debug( "current context URL: " + newJellyContext.currentURL );

702

             }

703

704

130

             script.run(newJellyContext, output);

705

706

130

             return newJellyContext;

707

         }

708

709

         /**

710

          * Returns a URL for the given resource from the specified path.

711

          * If the uri starts with "/" then the path is taken as relative to

712

          * the current context root.

713

          * If the uri is a well formed URL then it is used.

714

          * If the uri is a file that exists and can be read then it is used.

715

          * Otherwise the uri is interpreted as relative to the current context (the

716

          * location of the current script).

717

          */

718

         public URL getResource(String uri) throws MalformedURLException {

719

104

             if (uri.startsWith("/")) {

720

                 // append this uri to the context root

721

0

                 return createRelativeURL(rootURL, uri.substring(1));

722

             }

723

             else {

724

                 try {

725

104

                     return new URL(uri);

726

                 }

727

104

                 catch (MalformedURLException e) {

728

                     // lets try find a relative resource

729

                     try {

730

104

                         return createRelativeURL(currentURL, uri);

731

0

                     } catch (MalformedURLException e2) {

732

0

                         throw e;

733

                     }

734

                 }

735

             }

736

         }

737

738

         /**

739

          * Attempts to open an InputStream to the given resource at the specified path.

740

          * If the uri starts with "/" then the path is taken as relative to

741

          * the current context root. If the uri is a well formed URL then it

742

          * is used. Otherwise the uri is interpreted as relative to the current

743

          * context (the location of the current script).

744

          *

745

          * @return null if this resource could not be loaded, otherwise the resources

746

          *  input stream is returned.

747

          */

748

         public InputStream getResourceAsStream(String uri) {

749

             try {

750

0

                 URL url = getResource(uri);

751

0

                 return url.openStream();

752

             }

753

0

             catch (Exception e) {

754

0

                 if (log.isTraceEnabled()) {

755

0

                     log.trace(

756

                         "Caught exception attempting to open: " + uri + ". Exception: " + e,

757

                         e);

758

                 }

759

0

                 return null;

760

             }

761

         }

762

763

764

         // Properties

765

         //-------------------------------------------------------------------------

766

767

         /**

768

          * @return the current root context URL from which all absolute resource URIs

769

          *  will be relative to. For example in a web application the root URL will

770

          *  map to the web directory which contains the WEB-INF directory.

771

          */

772

         public URL getRootURL() {

773

25259

             return rootURL;

774

         }

775

776

         /**

777

          * Sets the current root context URL from which all absolute resource URIs

778

          *  will be relative to. For example in a web application the root URL will

779

          *  map to the web directory which contains the WEB-INF directory.

780

          */

781

         public void setRootURL(URL rootURL) {

782

13299

             this.rootURL = rootURL;

783

13299

         }

784

785

786

         /**

787

          * @return the current URL context of the current script that is executing.

788

          *  This URL context is used to deduce relative scripts when relative URIs are

789

          *  used in calls to {@link #getResource} to process relative scripts.

790

          */

791

         public URL getCurrentURL() {

792

25584

             return currentURL;

793

         }

794

795

         /**

796

          * Sets the current URL context of the current script that is executing.

797

          *  This URL context is used to deduce relative scripts when relative URIs are

798

          *  used in calls to {@link #getResource} to process relative scripts.

799

          */

800

         public void setCurrentURL(URL currentURL) {

801

13299

             this.currentURL = currentURL;

802

13299

         }

803

804

         /**

805

          * Returns whether we export tag libraries to our parents context

806

          * @return boolean

807

          */

808

         public boolean isExportLibraries() {

809

35126

             return exportLibraries;

810

         }

811

812

         /**

813

          * Sets whether we export tag libraries to our parents context

814

          * @param exportLibraries The exportLibraries to set

815

          */

816

         public void setExportLibraries(boolean exportLibraries) {

817

247

             this.exportLibraries = exportLibraries;

818

247

         }

819

820

821

         /**

822

          * Sets whether we should export variable definitions to our parent context

823

          */

824

         public void setExport(boolean export) {

825

377

             this.export = export;

826

377

         }

827

828

         /**

829

          * @return whether we should export variable definitions to our parent context

830

          */

831

         public boolean isExport() {

832

6448

             return this.export;

833

         }

834

835

         /**

836

          * Sets whether we should inherit variables from our parent context

837

          */

838

         public void setInherit(boolean inherit) {

839

130

             this.inherit = inherit;

840

130

         }

841

842

         /**

843

          * @return whether we should inherit variables from our parent context

844

          */

845

         public boolean isInherit() {

846

9113

             return this.inherit;

847

         }

848

849

850

         /**

851

          * Return the class loader to be used for instantiating application objects

852

          * when required.  This is determined based upon the following rules:

853

          * <ul>

854

          * <li>The class loader set by <code>setClassLoader()</code>, if any</li>

855

          * <li>The thread context class loader, if it exists and the

856

          *     <code>useContextClassLoader</code> property is set to true</li>

857

          * <li>The class loader used to load the XMLParser class itself.

858

          * </ul>

859

          */

860

         public ClassLoader getClassLoader() {

861

936

             return ClassLoaderUtils.getClassLoader(classLoader, useContextClassLoader, getClass());

862

         }

863

864

         /**

865

          * Set the class loader to be used for instantiating application objects

866

          * when required.

867

          *

868

          * @param classLoader The new class loader to use, or <code>null</code>

869

          *  to revert to the standard rules

870

          */

871

         public void setClassLoader(ClassLoader classLoader) {

872

0

             this.classLoader = classLoader;

873

0

         }

874

875

         /**

876

          * Return the boolean as to whether the context classloader should be used.

877

          */

878

         public boolean getUseContextClassLoader() {

879

0

             return useContextClassLoader;

880

         }

881

882

         /**

883

          * Determine whether to use the Context ClassLoader (the one found by

884

          * calling <code>Thread.currentThread().getContextClassLoader()</code>)

885

          * to resolve/load classes.  If not

886

          * using Context ClassLoader, then the class-loading defaults to

887

          * using the calling-class' ClassLoader.

888

          *

889

          * @param use determines whether to use JellyContext ClassLoader.

890

          */

891

         public void setUseContextClassLoader(boolean use) {

892

0

             useContextClassLoader = use;

893

0

         }

894

895

896

         // Implementation methods

897

         //-------------------------------------------------------------------------

898

         /**

899

          * @return a new relative URL from the given root and with the addition of the

900

          * extra relative URI

901

          *

902

          * @param rootURL is the root context from which the relative URI will be applied

903

          * @param relativeURI is the relative URI (without a leading "/")

904

          * @throws MalformedURLException if the URL is invalid.

905

          */

906

         protected URL createRelativeURL(URL rootURL, String relativeURI)

907

             throws MalformedURLException {

908

104

             URL url = rootURL;

909

104

             if (url == null) {

910

0

                 File file = new File(System.getProperty("user.dir"));

911

0

                 url = file.toURL();

912

             }

913

104

             String urlText = url.toString() + relativeURI;

914

104

             if ( log.isDebugEnabled() ) {

915

0

                 log.debug("Attempting to open url: " + urlText);

916

             }

917

104

             return new URL(urlText);

918

         }

919

920

         /**

921

          * Strips off the name of a script to create a new context URL

922

          */

923

         protected URL getJellyContextURL(URL url) throws MalformedURLException {

924

0

             String text = url.toString();

925

0

             int idx = text.lastIndexOf('/');

926

0

             text = text.substring(0, idx + 1);

927

0

             return new URL(text);

928

         }

929

930

         /**

931

          * Strips off the name of a script to create a new context URL

932

          */

933

         protected URL getJellyContextURL(InputSource source) throws MalformedURLException {

934

130

             String text = source.getSystemId();

935

130

             if (text != null) {

936

117

                 int idx = text.lastIndexOf('/');

937

117

                 text = text.substring(0, idx + 1);

938

117

                 return new URL(text);

939

             } else {

940

13

                 return null;

941

             }

942

943

         }

944

945

         /**

946

          * Factory method to create a new child of this context

947

          */

948

         protected JellyContext createChildContext() {

949

156

             return new JellyContext(this);

950

         }

951

952

         /**

953

          * Change the parent context to the one provided

954

          * @param context the new parent context

955

          */

956

         protected void setParent(JellyContext context)

957

         {

958

0

             parent = context;

959

0

             this.variables.put("parentScope", parent.variables);

960

             // need to re-export tag libraries to the new parent

961

0

             if (isExportLibraries() && parent != null) {

962

0

                 for (Iterator keys = taglibs.keySet().iterator(); keys.hasNext();)

963

                 {

964

0

                     String namespaceURI = (String) keys.next();

965

0

                     Object tagLibOrClassName = taglibs.get(namespaceURI);

966

0

                     if (tagLibOrClassName instanceof TagLibrary)

967

                     {

968

0

                         parent.registerTagLibrary( namespaceURI, (TagLibrary) tagLibOrClassName );

969

0

                     }

970

                     else

971

                     {

972

0

                         parent.registerTagLibrary( namespaceURI, (String) tagLibOrClassName );

973

                     }

974

0

                 }

975

             }

976

977

0

         }

978

979

     }

This report is generated by jcoverage, Maven and Maven JCoverage Plugin.