Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: nextapp/echoservlet/util/PeerFactory.java


1   /* 
2    * This file is part of the Echo Web Application Framework (hereinafter "Echo").
3    * Copyright (C) 2002-2004 NextApp, Inc.
4    *
5    * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6    *
7    * The contents of this file are subject to the Mozilla Public License Version
8    * 1.1 (the "License"); you may not use this file except in compliance with
9    * the License. You may obtain a copy of the License at
10   * http://www.mozilla.org/MPL/
11   *
12   * Software distributed under the License is distributed on an "AS IS" basis,
13   * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14   * for the specific language governing rights and limitations under the
15   * License.
16   *
17   * Alternatively, the contents of this file may be used under the terms of
18   * either the GNU General Public License Version 2 or later (the "GPL"), or
19   * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
20   * in which case the provisions of the GPL or the LGPL are applicable instead
21   * of those above. If you wish to allow use of your version of this file only
22   * under the terms of either the GPL or the LGPL, and not to allow others to
23   * use your version of this file under the terms of the MPL, indicate your
24   * decision by deleting the provisions above and replace them with the notice
25   * and other provisions required by the GPL or the LGPL. If you do not delete
26   * the provisions above, a recipient may use your version of this file under
27   * the terms of any one of the MPL, the GPL or the LGPL.
28   */
29   
30  package nextapp.echoservlet.util;
31  
32  import java.io.Serializable;
33  import java.util.Map;
34  import java.util.MissingResourceException;
35  
36  /**
37   * Generates "peer" objects for objects based on associations.
38   * Associations are stored in a properties files, where the keys are the fully
39   * qualified class names of objects and the values are the fully qualified
40   * class names of their peers.  When an object is passed to the createPeer()
41   * method its peer will be returned based on the bindings in the properties file.
42   * An objects superclass(es) will also be tested for available peers if none is
43   * available for the derived class.  If no peer is found, a PeerFactoryException
44   * is thrown.
45   */
46  public class PeerFactory 
47  implements Serializable {
48  
49      /**
50       * An exception used to describe a problem that was encountered loading
51       * a peer object.
52       */
53      public class PeerFactoryException extends Exception {
54      
55          /**
56           * Creates a <code>PeerFactoryException</code>.
57           *
58           * @param description A description of the problem which caused this
59           *        exception to occur.
60           */
61          public PeerFactoryException(String description) {
62              super(description);
63          }
64      }
65      
66      /** A map of associations */
67      private Map associations = null;
68      
69      /**
70       * Creates a new <code>PeerFactory</code>.
71       */
72      public PeerFactory() {
73          super();
74      }
75      
76      /** 
77       * Creates a new <code>PeerFactory</code> with initial associations.
78       *
79       * @param propertiesFile The name for the properties file containing the 
80       *        initial peer bindings.
81       */ 
82      public PeerFactory(String propertiesFile) 
83      throws PeerFactoryException { 
84          super();
85          
86          addAssociations(propertiesFile);
87      }
88      
89      /**
90       * Adds a single peer binding.
91       * 
92       * @param className The fully qualified name of the class.
93       * @param peerClassName The fully qualified name of the peer class.
94       */
95      public void addAssociation(String className, String peerClassName) {
96          associations.put(className, peerClassName);
97      }
98      
99      /**
100      * Loads peer bindings.  Invoking this method will result in the new
101      * associations supplementing existing associations.  Existing associations
102      * will not be removed.  If two associations have the same key, the most 
103      * recently added one will be used.
104      *
105      * @param propertiesFile The name of a properties file containing the peer 
106      *        bindings to be loaded. 
107      */
108     public void addAssociations(String propertiesFile)
109     throws PeerFactoryException {
110         try {
111             if (associations == null) {
112                 associations = new PropertyMap(propertiesFile);
113             } else {
114                 associations.putAll(new PropertyMap(propertiesFile));
115             }
116         } catch (MissingResourceException ex) {
117             throw new PeerFactoryException("Unable to load associations file \"" + propertiesFile + "\":" + ex);
118         }
119     }
120 
121     /**
122      * Instantiates a new peer for the specified object by invoking its
123      * default constructor.
124      *
125      * @param object The object for which to create an peer instance.
126      * @return A new instance of the peer object for <code>object</code>.
127      * @throws PeerFactoryException if the peer cannot be instantiated.
128      */
129     public Object createPeer(Object object) 
130     throws PeerFactoryException {
131         Object peer = null;
132         Class peerClass = getPeerClass(object.getClass());
133         
134         try {
135             peer = peerClass.newInstance();
136         } catch (InstantiationException ex) {
137             throw new PeerFactoryException("Unable to instantiate peer class \"" + peerClass.getName()
138                     + "\":" + ex);
139         } catch (IllegalAccessException ex) {
140             throw new PeerFactoryException("Unable to access peer class \"" + peerClass.getName()
141                     + "\":" + ex);
142         }
143         
144         return peer;
145     }
146     
147     /**
148      * Returns the peer class associated for the given object class.
149      *
150      * @param objectClass The <code>Class</code> of the object whose peer
151      *        <code>Class</code> is to be determined.
152      * @return The <code>Class</code> of the corresponding peer.
153      * @throws PeerFactoryException if the peer class cannot be determined.
154      */
155     public Class getPeerClass(Class objectClass) 
156     throws PeerFactoryException {
157         String objectClassName = null;
158         String originalObjectClassName = objectClass.getName();
159         String peerClassName = null;
160         Class peerClass;
161 
162         while (peerClassName == null) { 
163             objectClassName = objectClass.getName();
164 
165             peerClassName = (String) associations.get(objectClassName);
166 
167             if (peerClassName == null) {
168                 objectClass = objectClass.getSuperclass();
169                 if (objectClass == null) {
170                     throw new PeerFactoryException("No peer class is registered for \"" + originalObjectClassName + "\".");
171                 }
172             }
173         }
174         
175         try {
176             peerClass = Thread.currentThread().getContextClassLoader().loadClass(peerClassName);
177         } catch (ClassNotFoundException ex) {
178             throw new PeerFactoryException("Unable to find peer class \"" + peerClassName 
179                     + "\" for object \"" + objectClassName +  "\": ");
180         }
181 
182         return peerClass;
183     }
184 }