Metadata provider now supports inline metadata specification.
[java-idp.git] / src / edu / internet2 / middleware / shibboleth / metadata / provider / XMLMetadata.java
1 /*
2  * The Shibboleth License, Version 1. Copyright (c) 2002 University Corporation for Advanced Internet Development, Inc.
3  * All rights reserved Redistribution and use in source and binary forms, with or without modification, are permitted
4  * provided that the following conditions are met: Redistributions of source code must retain the above copyright
5  * notice, this list of conditions and the following disclaimer. Redistributions in binary form must reproduce the above
6  * copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials
7  * provided with the distribution, if any, must include the following acknowledgment: "This product includes software
8  * developed by the University Corporation for Advanced Internet Development <http://www.ucaid.edu>Internet2 Project.
9  * Alternately, this acknowledegement may appear in the software itself, if and wherever such third-party
10  * acknowledgments normally appear. Neither the name of Shibboleth nor the names of its contributors, nor Internet2, nor
11  * the University Corporation for Advanced Internet Development, Inc., nor UCAID may be used to endorse or promote
12  * products derived from this software without specific prior written permission. For written permission, please contact
13  * shibboleth@shibboleth.org Products derived from this software may not be called Shibboleth, Internet2, UCAID, or the
14  * University Corporation for Advanced Internet Development, nor may Shibboleth appear in their name, without prior
15  * written permission of the University Corporation for Advanced Internet Development. THIS SOFTWARE IS PROVIDED BY THE
16  * COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND WITH ALL FAULTS. ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
17  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT ARE
18  * DISCLAIMED AND THE ENTIRE RISK OF SATISFACTORY QUALITY, PERFORMANCE, ACCURACY, AND EFFORT IS WITH LICENSEE. IN NO
19  * EVENT SHALL THE COPYRIGHT OWNER, CONTRIBUTORS OR THE UNIVERSITY CORPORATION FOR ADVANCED INTERNET DEVELOPMENT, INC.
20  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
21  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
23  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 package edu.internet2.middleware.shibboleth.metadata.provider;
27
28 import java.io.IOException;
29
30 import org.apache.log4j.Logger;
31 import org.opensaml.SAMLException;
32 import org.opensaml.XML;
33 import org.opensaml.artifact.Artifact;
34 import org.w3c.dom.Document;
35 import org.w3c.dom.Element;
36 import org.w3c.dom.NodeList;
37 import org.xml.sax.InputSource;
38 import org.xml.sax.SAXException;
39
40 import edu.internet2.middleware.shibboleth.common.ResourceWatchdog;
41 import edu.internet2.middleware.shibboleth.common.ResourceWatchdogExecutionException;
42 import edu.internet2.middleware.shibboleth.common.ShibResource;
43 import edu.internet2.middleware.shibboleth.common.ShibResource.ResourceNotAvailableException;
44 import edu.internet2.middleware.shibboleth.metadata.EntityDescriptor;
45 import edu.internet2.middleware.shibboleth.metadata.Metadata;
46 import edu.internet2.middleware.shibboleth.metadata.MetadataException;
47 import edu.internet2.middleware.shibboleth.xml.Parser;
48
49 /**
50  * @author Walter Hoehn (wassa@columbia.edu)
51  */
52 public class XMLMetadata extends ResourceWatchdog implements Metadata {
53
54         private static Logger log = Logger.getLogger(XMLMetadataLoadWrapper.class.getName());
55         private Metadata currentMeta;
56
57         public XMLMetadata(Element configuration) throws MetadataException, ResourceNotAvailableException {
58
59                 super(new ShibResource(configuration.getAttribute("uri"), XMLMetadata.class));
60
61                 try {
62
63                         if (configuration.getAttribute("uri") != null && !configuration.getAttribute("uri").equals("")) {
64                                 // The configuration points to a metadata file
65                                 InputSource src = new InputSource(resource.getInputStream());
66                                 src.setSystemId(resource.getURL().toString());
67                                 Document doc = Parser.loadDom(src, true);
68                                 currentMeta = new XMLMetadataProvider(doc.getDocumentElement());
69
70                                 // Start checking for metadata updates
71                                 start();
72
73                         } else {
74                                 // Hopefully, the configuration is inline (don't reload in this case)
75                                 NodeList children = configuration.getChildNodes();
76                                 for (int i = 0; i < children.getLength(); i++) {
77
78                                         if ((children.item(i) instanceof Element)
79                                                         && (XML.isElementNamed((Element) children.item(i),
80                                                                         edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS, "EntitiesDescriptor") || XML
81                                                                         .isElementNamed((Element) children.item(i),
82                                                                                         edu.internet2.middleware.shibboleth.common.XML.SAML2META_NS,
83                                                                                         "EntityDescriptor"))) {
84                                                 currentMeta = new XMLMetadataProvider((Element) children.item(i));
85                                                 return;
86                                         }
87                                 }
88                                 // We didn't find a uri pointer or inline metadata, bail out
89                                 log.error("Encountered a problem reading metadata: <MetadataProvider/> configuration must "
90                                                 + "include either a (uri) attribute or inline metadata.");
91                                 throw new MetadataException("Unable to read metadata.");
92                         }
93
94                 } catch (IOException e) {
95                         log.error("Encountered a problem reading metadata source: " + e);
96                         throw new MetadataException("Unable to read metadata: " + e);
97                 } catch (SAXException e) {
98                         log.error("Encountered a problem parsing metadata source: " + e);
99                         throw new MetadataException("Unable to read metadata: " + e);
100                 } catch (SAMLException e) {
101                         log.error("Encountered a problem processing metadata source: " + e);
102                         throw new MetadataException("Unable to read metadata: + e");
103                 }
104
105         }
106
107         public XMLMetadata(String sitesFileLocation) throws MetadataException, ResourceNotAvailableException {
108
109                 super(new ShibResource(sitesFileLocation, XMLMetadata.class));
110                 try {
111                         InputSource src = new InputSource(resource.getInputStream());
112                         src.setSystemId(resource.getURL().toString());
113                         Document doc = Parser.loadDom(src, true);
114                         currentMeta = new XMLMetadataProvider(doc.getDocumentElement());
115                 } catch (IOException e) {
116                         log.error("Encountered a problem reading metadata source: " + e);
117                         throw new MetadataException("Unable to read metadata: " + e);
118                 } catch (SAXException e) {
119                         log.error("Encountered a problem parsing metadata source: " + e);
120                         throw new MetadataException("Unable to read metadata: " + e);
121                 } catch (SAMLException e) {
122                         log.error("Encountered a problem processing metadata source: " + e);
123                         throw new MetadataException("Unable to read metadata: + e");
124                 }
125
126                 // Start checking for metadata updates
127                 start();
128
129         }
130
131         public EntityDescriptor lookup(String providerId) {
132
133                 synchronized (currentMeta) {
134                         return currentMeta.lookup(providerId);
135                 }
136         }
137
138         public EntityDescriptor lookup(Artifact artifact) {
139
140                 synchronized (currentMeta) {
141                         return currentMeta.lookup(artifact);
142                 }
143         }
144
145         protected void doOnChange() throws ResourceWatchdogExecutionException {
146
147                 Metadata newMeta = null;
148                 Document newDoc = null;
149
150                 try {
151                         log.info("Detected a change in the metadata. Reloading from (" + resource.getURL().toString() + ").");
152                         newMeta = new XMLMetadataProvider(XML.parserPool.parse(resource.getInputStream()).getDocumentElement());
153                 } catch (IOException e) {
154                         log.error("Encountered an error retrieving updated SAML metadata, continuing to use stale copy: " + e);
155                         return;
156                 } catch (SAXException e) {
157                         log.error("Encountered an error retrieving updated SAML metadata, continuing to use stale copy: " + e);
158                         return;
159                 } catch (SAMLException e) {
160                         log.error("Encountered an error retrieving updated SAML metadata, continuing to use stale copy: " + e);
161                         return;
162                 }
163
164                 if (newMeta != null) {
165                         synchronized (currentMeta) {
166                                 currentMeta = newMeta;
167                         }
168                 }
169         }
170 }