View Javadoc

1   /***
2    *
3    * Copyright 2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   *  Unless required by applicable law or agreed to in writing, software
12   *  distributed under the License is distributed on an "AS IS" BASIS,
13   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   *  See the License for the specific language governing permissions and
15   *  limitations under the License.
16   */
17  package org.apache.pluto.portalImpl.services.portletdefinitionregistry;
18  
19  import java.io.BufferedReader;
20  import java.io.IOException;
21  import java.io.InputStream;
22  import java.io.InputStreamReader;
23  import java.util.ArrayList;
24  import java.util.HashMap;
25  import java.util.Iterator;
26  import java.util.List;
27  import java.util.Map;
28  import java.util.Vector;
29  
30  import javax.servlet.ServletConfig;
31  import javax.servlet.ServletContext;
32  import javax.servlet.UnavailableException;
33  
34  import org.apache.pluto.om.common.ObjectID;
35  import org.apache.pluto.om.portlet.PortletApplicationDefinition;
36  import org.apache.pluto.om.portlet.PortletApplicationDefinitionList;
37  import org.apache.pluto.om.portlet.PortletDefinition;
38  import org.apache.pluto.portalImpl.om.portlet.impl.PortletApplicationDefinitionImpl;
39  import org.apache.pluto.portalImpl.om.portlet.impl.PortletApplicationDefinitionListImpl;
40  import org.apache.pluto.portalImpl.om.servlet.impl.WebApplicationDefinitionImpl;
41  import org.apache.pluto.portalImpl.util.Properties;
42  import org.apache.pluto.portalImpl.xml.Constants;
43  import org.apache.pluto.portalImpl.xml.XmlParser.EntityResolver;
44  import org.exolab.castor.mapping.Mapping;
45  import org.exolab.castor.mapping.MappingException;
46  import org.exolab.castor.xml.MarshalException;
47  import org.exolab.castor.xml.Unmarshaller;
48  import org.exolab.castor.xml.ValidationException;
49  import org.xml.sax.InputSource;
50  
51  /***
52   * A version of the registry service that obtains data from a ServletContext
53   * rather than trying to scan for portlet applications.
54   *
55   * @version $Rev$ $Date$
56   */
57  public class PortletDefinitionRegistryServiceContextImpl extends PortletDefinitionRegistryService {
58      public static final String DEFAULT_CONTEXTS = "/WEB-INF/data/portletcontexts.txt";
59  
60      public final static String DEFAULT_MAPPING_PORTLETXML = "/WEB-INF/data/xml/portletdefinitionmapping.xml";
61      public final static String DEFAULT_MAPPING_WEBXML = "/WEB-INF/data/xml/servletdefinitionmapping.xml";
62  
63      private static final String CONFIG_MAPPING_PORTLETXML = "mapping.portletxml.configfile";
64      private static final String CONFIG_MAPPING_WEBXML = "mapping.webxml.configfile";
65  
66      private Mapping webXmlMapping;
67      private Mapping portletXmlMapping;
68  
69      private PortletApplicationDefinitionListImpl registry;
70      private Map definitions;
71  
72      public PortletApplicationDefinitionList getPortletApplicationDefinitionList() {
73          return registry;
74      }
75  
76      public PortletDefinition getPortletDefinition(ObjectID id) {
77          return (PortletDefinition) definitions.get(id);
78      }
79  
80      protected void init(ServletConfig config, Properties props) throws Exception {
81          ServletContext context = config.getServletContext();
82          portletXmlMapping = loadMapping(context, props.getString(CONFIG_MAPPING_PORTLETXML, DEFAULT_MAPPING_PORTLETXML));
83          webXmlMapping = loadMapping(context, props.getString(CONFIG_MAPPING_WEBXML, DEFAULT_MAPPING_WEBXML));
84  
85          List contexts = loadDefinitionList(context, DEFAULT_CONTEXTS);
86          registry = new PortletApplicationDefinitionListImpl();
87          for (Iterator i = contexts.iterator(); i.hasNext();) {
88              String contextRoot = (String) i.next();
89              PortletApplicationDefinition portletApp = loadApplicationDefinition(context, contextRoot);
90              registry.add(portletApp);
91          }
92  
93          definitions = new HashMap();
94          for (Iterator i = registry.iterator(); i.hasNext();) {
95              PortletApplicationDefinition application = (PortletApplicationDefinition) i.next();
96  
97              for (Iterator j = application.getPortletDefinitionList().iterator(); j.hasNext();) {
98                  PortletDefinition portlet = (PortletDefinition) j.next();
99                  definitions.put(portlet.getId(), portlet);
100             }
101         }
102     }
103 
104     private Mapping loadMapping(ServletContext context, String path) throws UnavailableException {
105         InputSource source = new InputSource(context.getResourceAsStream(path));
106         Mapping mapping = new Mapping();
107         try {
108             mapping.loadMapping(source);
109         } catch (IOException e) {
110             throw (UnavailableException) new UnavailableException("Error reading mapping " + path).initCause(e);
111         } catch (MappingException e) {
112             throw (UnavailableException) new UnavailableException("Invalid mapping " + path).initCause(e);
113         }
114         return mapping;
115     }
116 
117     private List loadDefinitionList(ServletContext context, String path) throws UnavailableException {
118         InputStream stream = context.getResourceAsStream(path);
119         if (stream == null) {
120             throw new UnavailableException("Unable to load registry " + path);
121         }
122         BufferedReader reader = new BufferedReader(new InputStreamReader(stream));
123         try {
124             try {
125                 String line;
126                 List contexts = new ArrayList();
127                 while ((line = reader.readLine()) != null) {
128                     contexts.add(line.trim());
129                 }
130                 return contexts;
131             } finally {
132                 reader.close();
133             }
134         } catch (IOException e) {
135             throw (UnavailableException) new UnavailableException("Error reading registry from " + path).initCause(e);
136         }
137     }
138 
139     private PortletApplicationDefinition loadApplicationDefinition(ServletContext context, String path) throws UnavailableException {
140         // locate the portlet application's context
141         ServletContext appContext = context.getContext(path);
142         if (appContext == null) {
143             throw new UnavailableException("Unable to access context for " + path);
144         }
145 
146         // load its portlet.xml
147         InputStream stream = appContext.getResourceAsStream("/WEB-INF/portlet.xml");
148         if (stream == null) {
149             throw new UnavailableException("No portlet.xml found in context " + appContext.getServletContextName());
150         }
151         InputSource source = new InputSource(stream);
152         Unmarshaller unmarshaller;
153         try {
154             unmarshaller = new Unmarshaller(portletXmlMapping);
155             unmarshaller.setEntityResolver(new EntityResolver(Constants.RES_PORTLET_DTDS, Constants.RES_PORTLET_DTD_NAMES));
156         } catch (MappingException e) {
157             throw (UnavailableException) new UnavailableException("Unable to construct unmarshaller for portlet.xml").initCause(e);
158         }
159         unmarshaller.setIgnoreExtraElements(true);
160         PortletApplicationDefinitionImpl portletApp;
161         try {
162             portletApp = (PortletApplicationDefinitionImpl) unmarshaller.unmarshal(source);
163         } catch (MarshalException e) {
164             throw (UnavailableException) new UnavailableException("Unable to unmarshal portlet.xml from context " + appContext.getServletContextName()).initCause(e);
165         } catch (ValidationException e) {
166             throw (UnavailableException) new UnavailableException("Unable to validate portlet.xml from context " + appContext.getServletContextName()).initCause(e);
167         }
168 
169         // load its web.xml
170         stream = appContext.getResourceAsStream("/WEB-INF/web.xml");
171         if (stream == null) {
172             throw new UnavailableException("No web.xml found in context " + appContext.getServletContextName());
173         }
174         source = new InputSource(stream);
175         try {
176             unmarshaller = new Unmarshaller(webXmlMapping);
177             unmarshaller.setEntityResolver(new EntityResolver(Constants.RES_WEB_PUBLIC_ID,
178                                                        Constants.RES_WEB_DTD,
179                                                        Constants.RES_WEB_DTD_NAME));
180         } catch (MappingException e) {
181             throw (UnavailableException) new UnavailableException("Unable to construct unmarshaller for web.xml").initCause(e);
182         }
183         unmarshaller.setIgnoreExtraElements(true);
184 
185         WebApplicationDefinitionImpl webApp;
186         try {
187             webApp = (WebApplicationDefinitionImpl) unmarshaller.unmarshal(source);
188         } catch (MarshalException e) {
189             throw (UnavailableException) new UnavailableException("Unable to unmarshal web.xml from context " + appContext.getServletContextName()).initCause(e);
190         } catch (ValidationException e) {
191             throw (UnavailableException) new UnavailableException("Unable to validate web.xml from context " + appContext.getServletContextName()).initCause(e);
192         }
193 
194         Vector structure = new Vector();
195         structure.add(portletApp);
196         structure.add(path);
197 
198         try {
199             webApp.postLoad(structure);
200             webApp.preBuild(structure);
201             webApp.postBuild(structure);
202         } catch (Exception e) {
203             throw (UnavailableException) new UnavailableException(e.getMessage()).initCause(e);
204         }
205         return portletApp;
206     }
207 }
208