001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.cocoon.webapps.authentication.components;
018:
019: import java.io.IOException;
020:
021: import org.apache.avalon.framework.activity.Disposable;
022: import org.apache.avalon.framework.logger.AbstractLogEnabled;
023: import org.apache.avalon.framework.service.ServiceException;
024: import org.apache.avalon.framework.service.ServiceManager;
025: import org.apache.avalon.framework.service.Serviceable;
026: import org.apache.avalon.framework.thread.ThreadSafe;
027: import org.apache.cocoon.ProcessingException;
028: import org.apache.cocoon.components.source.SourceUtil;
029: import org.apache.cocoon.webapps.authentication.configuration.HandlerConfiguration;
030: import org.apache.cocoon.webapps.authentication.user.UserHandler;
031: import org.apache.cocoon.webapps.session.MediaManager;
032: import org.apache.cocoon.xml.XMLUtils;
033: import org.apache.cocoon.xml.dom.DOMUtil;
034: import org.apache.excalibur.source.Source;
035: import org.apache.excalibur.source.SourceException;
036: import org.apache.excalibur.source.SourceParameters;
037: import org.apache.excalibur.source.SourceResolver;
038: import org.w3c.dom.Document;
039: import org.w3c.dom.Element;
040: import org.w3c.dom.Node;
041: import org.w3c.dom.NodeList;
042: import org.w3c.dom.Text;
043: import org.xml.sax.SAXException;
044:
045: /**
046: * Verify if a user can be authenticated.
047: *
048: * @author <a href="mailto:cziegeler@apache.org">Carsten Ziegeler</a>
049: * @deprecated This block is deprecated and will be removed in future versions.
050: * @version CVS $Id: PipelineAuthenticator.java 433543 2006-08-22 06:22:54Z crossley $
051: */
052: public class PipelineAuthenticator extends AbstractLogEnabled implements
053: Serviceable, ThreadSafe, Disposable, Authenticator {
054:
055: /** The service manager */
056: protected ServiceManager manager;
057:
058: /** The source resolver */
059: protected SourceResolver resolver;
060:
061: /**
062: * Check the fragment if it is valid
063: */
064: private boolean isValidAuthenticationFragment(
065: Document authenticationFragment) throws ProcessingException {
066: // calling method is synced
067: if (getLogger().isDebugEnabled()) {
068: getLogger()
069: .debug(
070: "BEGIN isValidAuthenticationFragment fragment="
071: + XMLUtils
072: .serializeNode(
073: authenticationFragment,
074: XMLUtils
075: .createPropertiesForXML(false)));
076: }
077: boolean isValid = false;
078:
079: // authenticationFragment must only have exactly one child with
080: // the name authentication
081: if (authenticationFragment.hasChildNodes() == true
082: && authenticationFragment.getChildNodes().getLength() == 1) {
083: Node child = authenticationFragment.getFirstChild();
084:
085: if (child.getNodeType() == Node.ELEMENT_NODE
086: && child.getNodeName().equals("authentication") == true) {
087:
088: // now authentication must have one child ID
089: if (child.hasChildNodes() == true) {
090: NodeList children = child.getChildNodes();
091: boolean found = false;
092: int i = 0;
093: int l = children.getLength();
094:
095: while (found == false && i < l) {
096: child = children.item(i);
097: if (child.getNodeType() == Node.ELEMENT_NODE
098: && child.getNodeName().equals("ID") == true) {
099: found = true;
100: } else {
101: i++;
102: }
103: }
104:
105: // now the last check: ID must have a TEXT child
106: if (found == true) {
107: child.normalize(); // join text nodes
108: if (child.hasChildNodes() == true
109: && child.getChildNodes().getLength() == 1
110: && child.getChildNodes().item(0)
111: .getNodeType() == Node.TEXT_NODE) {
112: String value = child.getChildNodes()
113: .item(0).getNodeValue().trim();
114: if (value.length() > 0)
115: isValid = true;
116: }
117: }
118: }
119:
120: }
121: }
122: if (this .getLogger().isDebugEnabled()) {
123: this .getLogger().debug(
124: "END isValidAuthenticationFragment valid="
125: + isValid);
126: }
127: return isValid;
128: }
129:
130: /* (non-Javadoc)
131: * @see org.apache.cocoon.webapps.authentication.components.Authenticator#authenticate(org.apache.cocoon.webapps.authentication.configuration.HandlerConfiguration, org.apache.excalibur.source.SourceParameters)
132: */
133: public AuthenticationResult authenticate(
134: HandlerConfiguration configuration,
135: SourceParameters parameters) throws ProcessingException {
136: if (this .getLogger().isDebugEnabled()) {
137: this .getLogger().debug(
138: "start authenticator using handler "
139: + configuration.getName());
140: }
141:
142: final String authenticationResourceName = configuration
143: .getAuthenticationResource();
144: final SourceParameters authenticationParameters = configuration
145: .getAuthenticationResourceParameters();
146: if (parameters != null) {
147: parameters.add(authenticationParameters);
148: } else {
149: parameters = authenticationParameters;
150: }
151:
152: Document doc = null;
153: String exceptionMsg = null;
154:
155: // invoke the source
156: try {
157: Source source = null;
158: try {
159: source = SourceUtil.getSource(
160: authenticationResourceName, null, parameters,
161: this .resolver);
162: doc = SourceUtil.toDOM(source);
163: } catch (SAXException se) {
164: throw new ProcessingException(se);
165: } catch (SourceException se) {
166: throw SourceUtil.handle(se);
167: } catch (IOException e) {
168: throw new ProcessingException(e);
169: } finally {
170: this .resolver.release(source);
171: }
172: } catch (ProcessingException local) {
173: this .getLogger().error(
174: "authenticator: " + local.getMessage(), local);
175: exceptionMsg = local.getMessage();
176: }
177:
178: // test if authentication was successful
179: boolean isValid = false;
180: AuthenticationResult result = null;
181: if (doc != null) {
182: isValid = this .isValidAuthenticationFragment(doc);
183:
184: if (isValid) {
185: if (this .getLogger().isInfoEnabled()) {
186: this .getLogger().info(
187: "Authenticator: User authenticated using handler '"
188: + configuration.getName() + "'");
189: }
190:
191: MediaManager mediaManager = null;
192: String mediaType;
193: try {
194: mediaManager = (MediaManager) this .manager
195: .lookup(MediaManager.ROLE);
196: mediaType = mediaManager.getMediaType();
197: } catch (ServiceException se) {
198: throw new ProcessingException(
199: "Unable to lookup media manager.", se);
200: } finally {
201: this .manager.release(mediaManager);
202: }
203: synchronized (configuration) {
204: // add special nodes to the authentication block:
205: // useragent, type and media
206: Element specialElement;
207: Text specialValue;
208: Element authNode;
209:
210: authNode = (Element) doc.getFirstChild();
211:
212: specialElement = doc.createElementNS(null, "type");
213: specialValue = doc
214: .createTextNode("cocoon.authentication");
215: specialElement.appendChild(specialValue);
216: authNode.appendChild(specialElement);
217:
218: specialElement = doc.createElementNS(null, "media");
219: specialValue = doc.createTextNode(mediaType);
220: specialElement.appendChild(specialValue);
221: authNode.appendChild(specialElement);
222:
223: result = new AuthenticationResult(true, doc);
224:
225: } // end sync
226: }
227: }
228:
229: if (!isValid) {
230: if (this .getLogger().isInfoEnabled()) {
231: this .getLogger().info(
232: "Authenticator: Failed authentication using handler '"
233: + configuration.getName() + "'");
234: }
235: // get the /authentication/data Node if available
236: Node data = null;
237:
238: if (doc != null) {
239: data = DOMUtil.getFirstNodeFromPath(doc, new String[] {
240: "authentication", "data" }, false);
241: }
242: doc = DOMUtil.createDocument();
243:
244: // now create the following xml:
245: // <root>
246: // <failed/>
247: // if data is available data is included, otherwise:
248: // <data>No information</data>
249: // If exception message contains info, it is included into failed
250: // </root>
251: final Element root = doc.createElementNS(null, "root");
252: doc.appendChild(root);
253: Element element = doc.createElementNS(null, "failed");
254: root.appendChild(element);
255:
256: if (exceptionMsg != null) {
257: Text text = doc.createTextNode(exceptionMsg);
258: element.appendChild(text);
259: }
260:
261: if (data == null) {
262: element = doc.createElementNS(null, "data");
263: root.appendChild(element);
264: Text text = doc
265: .createTextNode("No information available");
266: element.appendChild(text);
267: } else {
268: root.appendChild(doc.importNode(data, true));
269: }
270:
271: result = new AuthenticationResult(false, doc);
272: }
273:
274: if (this .getLogger().isDebugEnabled()) {
275: this .getLogger().debug("end authenticator");
276: }
277:
278: return result;
279: }
280:
281: /* (non-Javadoc)
282: * @see org.apache.avalon.framework.service.Serviceable#service(ServiceManager)
283: */
284: public void service(ServiceManager manager) throws ServiceException {
285: this .manager = manager;
286: this .resolver = (SourceResolver) this .manager
287: .lookup(SourceResolver.ROLE);
288: }
289:
290: /* (non-Javadoc)
291: * @see org.apache.avalon.framework.activity.Disposable#dispose()
292: */
293: public void dispose() {
294: if (this .manager != null) {
295: this .manager.release(this .resolver);
296: this .manager = null;
297: this .resolver = null;
298: }
299: }
300:
301: /* (non-Javadoc)
302: * @see org.apache.cocoon.webapps.authentication.components.Authenticator#logout(UserHandler)
303: */
304: public void logout(UserHandler handler) {
305: if (this .getLogger().isDebugEnabled()) {
306: this .getLogger().debug(
307: "logout using handler " + handler.getHandlerName());
308: }
309:
310: final HandlerConfiguration configuration = handler
311: .getHandlerConfiguration();
312: final String logoutResourceName = configuration
313: .getLogoutResource();
314: if (logoutResourceName != null) {
315: final SourceParameters parameters = configuration
316: .getAuthenticationResourceParameters();
317:
318: // invoke the source
319: Source source = null;
320: try {
321: // This allows arbitrary business logic to be called. Whatever is returned
322: // is ignored.
323: source = SourceUtil.getSource(logoutResourceName, null,
324: parameters, this .resolver);
325: SourceUtil.toDOM(source);
326: } catch (Exception ignore) {
327: this .getLogger().error(
328: "logout: " + ignore.getMessage(), ignore);
329: } finally {
330: this.resolver.release(source);
331: }
332: }
333: }
334: }
|