View Javadoc

1   /**
2    * This file Copyright (c) 2003-2010 Magnolia International
3    * Ltd.  (http://www.magnolia-cms.com). All rights reserved.
4    *
5    *
6    * This file is dual-licensed under both the Magnolia
7    * Network Agreement and the GNU General Public License.
8    * You may elect to use one or the other of these licenses.
9    *
10   * This file is distributed in the hope that it will be
11   * useful, but AS-IS and WITHOUT ANY WARRANTY; without even the
12   * implied warranty of MERCHANTABILITY or FITNESS FOR A
13   * PARTICULAR PURPOSE, TITLE, or NONINFRINGEMENT.
14   * Redistribution, except as permitted by whichever of the GPL
15   * or MNA you select, is prohibited.
16   *
17   * 1. For the GPL license (GPL), you can redistribute and/or
18   * modify this file under the terms of the GNU General
19   * Public License, Version 3, as published by the Free Software
20   * Foundation.  You should have received a copy of the GNU
21   * General Public License, Version 3 along with this program;
22   * if not, write to the Free Software Foundation, Inc., 51
23   * Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
24   *
25   * 2. For the Magnolia Network Agreement (MNA), this file
26   * and the accompanying materials are made available under the
27   * terms of the MNA which accompanies this distribution, and
28   * is available at http://www.magnolia-cms.com/mna.html
29   *
30   * Any modifications to this file must keep this entire header
31   * intact.
32   *
33   */
34  package info.magnolia.module.admininterface;
35  
36  import info.magnolia.cms.beans.config.ObservedManager;
37  import info.magnolia.cms.core.Content;
38  import info.magnolia.cms.util.ContentUtil;
39  import info.magnolia.cms.util.SystemContentWrapper;
40  import info.magnolia.cms.util.NodeDataUtil;
41  import info.magnolia.content2bean.Content2BeanException;
42  import info.magnolia.content2bean.Content2BeanUtil;
43  import info.magnolia.content2bean.TransformationState;
44  import info.magnolia.content2bean.impl.Content2BeanTransformerImpl;
45  import info.magnolia.objectfactory.Components;
46  
47  import java.lang.reflect.Constructor;
48  import java.util.HashMap;
49  import java.util.Iterator;
50  import java.util.Map;
51  
52  import javax.servlet.http.HttpServletRequest;
53  import javax.servlet.http.HttpServletResponse;
54  
55  import org.apache.commons.beanutils.BeanUtils;
56  import org.apache.commons.beanutils.ConstructorUtils;
57  
58  
59  /**
60   * Manages the page handlers. A page is a very simple dialog without any configuration.
61   * @author philipp
62   */
63  public class PageHandlerManager extends ObservedManager {
64  
65      /**
66       * The handlers
67       */
68      private final Map dialogPageHandlers = new HashMap();
69  
70      /**
71       * Find a handler by name
72       * @param name
73       * @param request
74       * @param response
75       * @return an instance of the handlers
76       */
77      public PageMVCHandler getPageHandler(String name, HttpServletRequest request, HttpServletResponse response) {
78  
79          PageDefinition pageDefinition = (PageDefinition) dialogPageHandlers.get(name);
80  
81          if (pageDefinition == null) {
82              log.warn("Page definition not found: \"{}\"", name);
83              return null;
84          }
85          return pageDefinition.newInstance(name, request, response);
86      }
87  
88      /**
89       * register the pages from the config
90       * @param defNode
91       */
92      protected void onRegister(Content defNode) {
93          // read the dialog configuration
94  
95          for (Iterator iter = ContentUtil.getAllChildren(defNode).iterator(); iter.hasNext();) {
96              Content pageNode = (Content) iter.next();
97  
98              PageDefinition pd = new RepositoryPageDefinition(new SystemContentWrapper(pageNode));
99              registerPageDefinition(pd);
100         }
101 
102     }
103 
104     public void registerPageDefinition(PageDefinition pageDefinition) {
105         dialogPageHandlers.put(pageDefinition.getName(), pageDefinition);
106     }
107 
108     /**
109      * @deprecated
110      */
111     public void registerPageDefinition(String name, PageDefinition pageDefinition) {
112         dialogPageHandlers.put(name, pageDefinition);
113     }
114 
115     /**
116      * @return Returns the instance.
117      */
118     public static PageHandlerManager getInstance() {
119         return Components.getSingleton(PageHandlerManager.class);
120     }
121 
122     protected void onClear() {
123         this.dialogPageHandlers.clear();
124     }
125 
126     public static interface PageDefinition {
127 
128         public String getName();
129 
130         public PageMVCHandler newInstance(String name, HttpServletRequest request, HttpServletResponse response);
131     }
132 
133     /**
134      * This class is used if you want to register a page that is not stored in the repository.
135      * @author philipp
136      * @version $Id: PageHandlerManager.java 34214 2010-05-06 08:55:36Z had $
137      */
138     public static class BasePageDefinition implements PageDefinition {
139         private final static org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(BasePageDefinition.class);
140 
141         private Map defaultProperties = new HashMap();
142 
143         private Class handlerClass;
144 
145         private String name;
146 
147         public BasePageDefinition(String name, Class handlerClass) {
148             this.name = name;
149             this.handlerClass = handlerClass;
150         }
151 
152         public Map getDefaultProperties() {
153             return this.defaultProperties;
154         }
155 
156         public void setDefaultProperties(Map defaultProperties) {
157             this.defaultProperties = defaultProperties;
158         }
159 
160         public Class getHandlerClass() {
161             return this.handlerClass;
162         }
163 
164         public void setHandlerClass(Class handlerClass) {
165             this.handlerClass = handlerClass;
166         }
167 
168         public String getName() {
169             return this.name;
170         }
171 
172         public void setName(String name) {
173             this.name = name;
174         }
175 
176         public PageMVCHandler newInstance(String name, HttpServletRequest request, HttpServletResponse response) {
177 
178             try {
179                 Constructor constructor = getHandlerClass().getConstructor(
180                     new Class[]{String.class, HttpServletRequest.class, HttpServletResponse.class});
181                 PageMVCHandler page = (PageMVCHandler) constructor.newInstance(new Object[]{name, request, response});
182                 BeanUtils.populate(page, getDefaultProperties());
183                 return page;
184             }
185             catch (Exception e) {
186                 log.error("Can't instantiate page [" + name + "]", e);
187                 throw new InvalidDialogPageHandlerException(name, e);
188             }
189 
190         }
191     }
192 
193     public static class RepositoryPageDefinition implements PageDefinition {
194 
195         private Content node;
196 
197         public RepositoryPageDefinition(Content node) {
198             this.node = node;
199         }
200 
201         public String getName() {
202             return NodeDataUtil.getString(this.node, "name", this.node.getName());
203         }
204 
205         public PageMVCHandler newInstance(String name, final HttpServletRequest request,
206             final HttpServletResponse response) {
207             try {
208                 return (PageMVCHandler) Content2BeanUtil.toBean(node, true, new Content2BeanTransformerImpl() {
209 
210                     public Object newBeanInstance(TransformationState state, Map properties)
211                         throws Content2BeanException {
212                         if (state.getLevel() == 1) {
213                             try {
214                                 return ConstructorUtils.invokeConstructor(
215                                     state.getCurrentType().getType(),
216                                     new Object[]{getName(), request, response});
217                             }
218                             catch (Exception e) {
219                                 throw new Content2BeanException("no proper constructor found", e);
220                             }
221                         }
222 
223                         return super.newBeanInstance(state, properties);
224                     }
225                 });
226             }
227             catch (Content2BeanException e) {
228                 throw new InvalidDialogPageHandlerException(this.getName(), e);
229             }
230         }
231     }
232 
233 }