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
141 ServletContext appContext = context.getContext(path);
142 if (appContext == null) {
143 throw new UnavailableException("Unable to access context for " + path);
144 }
145
146
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
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