View Javadoc

1   /*
2    *  Copyright (c) 2005, 2006 Imola Informatica.
3    *  All rights reserved. This program and the accompanying materials
4    *  are made available under the terms of the LGPL License v2.1
5    *  which accompanies this distribution, and is available at
6    *  http://www.gnu.org/licenses/lgpl.html
7    */
8   
9   
10  package it.imolinfo.jbi4cics.jbi;
11  
12  import it.imolinfo.jbi4cics.Logger;
13  import it.imolinfo.jbi4cics.LoggerFactory;
14  import java.util.HashMap;
15  import java.util.Map;
16  
17  /**
18   * A class loader implementation able to receive class definition that will be
19   * found and defined on request.
20   *
21   * @author <a href="mailto:rspazzoli@imolinfo.it">Raffaele Spazzoli</a>
22   * @author <a href="mailto:mcimatti@imolinfo.it">Marco Cimatti</a>
23   */
24  public final class BCELClassLoader extends ClassLoader {
25  
26      /**
27       * The logger for this class and its instances.
28       */
29      private static final Logger LOG
30              = LoggerFactory.getLogger(BCELClassLoader.class);
31  
32      /**
33       * The responsible to translate localized messages.
34       */
35      private static final Messages MESSAGES
36              = Messages.getMessages(BCELClassLoader.class);
37  
38      /**
39       * The bytecode of the classes added to (and loaded by) this
40       * <code>ClassLoader</code>, indexed by their name.
41       *
42       * @see #addClass(String, byte[])
43       */
44      private Map<String, byte[]> classesCode = new HashMap<String, byte[]>();
45  
46      /**
47       * Creates a new class loader using the specified parent class loader for
48       * delegation.
49       *
50       * @param  parent  the parent class loader.
51       */
52      public BCELClassLoader(final ClassLoader parent) {
53          super(parent);
54      }
55  
56      /**
57       * Adds a new class data to this class loader. After a call to this method,
58       * this class loader is able to find and define the new specified class, if
59       * parameters are valid.
60       *
61       * @param  className  the complete class name. Must be not
62       *                    <code>null</code>.
63       * @param  bytecode   the bytecode of the new class. Must be not
64       *                    <code>null</code> and it is considered all its
65       *                    content, starting from offset 0 and ending at offset
66       *                    <code>bytecode.length</code> - 1. It is recommended
67       *                    that the caller doesn't modify its content, because
68       *                    this array is cached <i>as is</i>, without cloning it.
69       */
70      public void addClass(final String className, final byte[] bytecode) {
71          classesCode.put(className, bytecode);
72      }
73  
74      /**
75       * Finds the class with the specified binary name, searching in the pool of
76       * classes added by the {@link #addClass(String, byte[])} method.
77       *
78       * @param   name  the binary name of the class.
79       * @return  the resulting <code>Class</code> object.
80       * @throws  ClassNotFoundException  if the class could not be found, because
81       *                                  it's not been added to this class
82       *                                  loader.
83       * @see     #addClass(String, byte[])
84       */
85      @Override
86      protected Class<?> findClass(final String name)             // Overridden
87              throws ClassNotFoundException {
88          byte[] bytecode = classesCode.get(name);
89  
90          if (LOG.isDebugEnabled()) {
91              LOG.debug("findClass(" + name + ")");
92          }
93  
94          if (bytecode == null) {                         // Should never happen
95              throw new ClassNotFoundException(
96                      MESSAGES.getString("CIC001042_Class_not_found", name));
97          }
98          return defineClass(name, bytecode, 0, bytecode.length);
99      }
100 }