001: /*
002: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
003: *
004: * Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
005: *
006: * The contents of this file are subject to the terms of either the GNU
007: * General Public License Version 2 only ("GPL") or the Common Development
008: * and Distribution License("CDDL") (collectively, the "License"). You
009: * may not use this file except in compliance with the License. You can obtain
010: * a copy of the License at https://glassfish.dev.java.net/public/CDDL+GPL.html
011: * or glassfish/bootstrap/legal/LICENSE.txt. See the License for the specific
012: * language governing permissions and limitations under the License.
013: *
014: * When distributing the software, include this License Header Notice in each
015: * file and include the License file at glassfish/bootstrap/legal/LICENSE.txt.
016: * Sun designates this particular file as subject to the "Classpath" exception
017: * as provided by Sun in the GPL Version 2 section of the License file that
018: * accompanied this code. If applicable, add the following below the License
019: * Header, with the fields enclosed by brackets [] replaced by your own
020: * identifying information: "Portions Copyrighted [year]
021: * [name of copyright owner]"
022: *
023: * Contributor(s):
024: *
025: * If you wish your version of this file to be governed by only the CDDL or
026: * only the GPL Version 2, indicate your decision by adding "[Contributor]
027: * elects to include this software in this distribution under the [CDDL or GPL
028: * Version 2] license." If you don't indicate a single choice of license, a
029: * recipient has the option to distribute your version of this file under
030: * either the CDDL, the GPL Version 2 or to extend the choice of license to
031: * its licensees as provided above. However, if you add GPL Version 2 code
032: * and therefore, elected the GPL Version 2 license, then the option applies
033: * only if the new code is made subject to such option by the copyright
034: * holder.
035: */
036:
037: package com.sun.xml.ws.policy.jaxws;
038:
039: import java.io.IOException;
040: import java.net.URL;
041: import javax.xml.stream.XMLStreamException;
042:
043: import org.xml.sax.SAXException;
044: import com.sun.xml.ws.api.model.wsdl.WSDLModel;
045: import com.sun.xml.ws.api.server.Container;
046: import com.sun.xml.ws.api.server.SDDocumentSource;
047: import com.sun.xml.ws.api.wsdl.parser.WSDLParserExtension;
048: import com.sun.xml.ws.api.wsdl.parser.XMLEntityResolver;
049: import com.sun.xml.ws.policy.PolicyConstants;
050: import com.sun.xml.ws.policy.PolicyException;
051: import com.sun.xml.ws.policy.PolicyMap;
052: import com.sun.xml.ws.policy.PolicyMapMutator;
053: import com.sun.xml.ws.policy.jaxws.privateutil.LocalizationMessages;
054: import com.sun.xml.ws.policy.privateutil.PolicyLogger;
055: import com.sun.xml.ws.policy.privateutil.PolicyUtils;
056: import java.io.File;
057:
058: /**
059: * Reads a policy configuration file and returns the WSDL model generated from it.
060: *
061: * @author Marek Potociar (marek.potociar at sun.com)
062: */
063: public final class PolicyConfigParser {
064: private static final PolicyLogger LOGGER = PolicyLogger
065: .getLogger(PolicyConfigParser.class);
066:
067: private static final String SERVLET_CONTEXT_CLASSNAME = "javax.servlet.ServletContext";
068: // Prefixing with META-INF/ instead of /META-INF/. /META-INF/ is working fine
069: // when loading from a JAR file but not when loading from a plain directory.
070: private static final String JAR_PREFIX = "META-INF/";
071: private static final String WAR_PREFIX = "/WEB-INF/";
072:
073: /**
074: * Private constructor for the utility class to prevend class instantiation
075: */
076: private PolicyConfigParser() {
077: }
078:
079: /**
080: * This is a helper method that returns directly {@link PolicyMap} instance populated
081: * from information in WSIT config file. For more details on the whole process see
082: * {@link #parseModel(String, Container, PolicyMapMutator[]) parseModel}
083: * method.
084: *
085: * @param configFileIdentifier base of WSIT config file name (web service name for WSIT service
086: * config file or "client" for WSIT client configuration). Must not be {@code null}.
087: * @param container if the application is run inside a web container, the container instance
088: * should be passed into this function, in order to get access to the servlet context
089: * that is used to load config file stored in {@code WEB-INF} directory of the application.
090: * May be {@code null}.
091: * @param mutators to be registered with the populated {@link PolicyMap} object. May be
092: * ommited if user does not plan to modify the {@link PolicyMap} instance.
093: *
094: * @return A {@link WSDLModel} with a {@link PolicyMap} object populated with information read
095: * from the WSIT config file.
096: * @throws PolicyException in case of any problems that may occur while reading WSIT config file
097: * and constructing the {@link WSDLModel} object or populating {@link PolicyMap} instance.
098: */
099: public static PolicyMap parse(final String configFileIdentifier,
100: final Container container,
101: final PolicyMapMutator... mutators) throws PolicyException {
102: LOGGER.entering(configFileIdentifier, container, mutators);
103: PolicyMap map = null;
104: try {
105: return map = extractPolicyMap(parseModel(
106: configFileIdentifier, container, mutators));
107: } finally {
108: LOGGER.exiting(map);
109: }
110: }
111:
112: /**
113: * This is a helper method that returns directly {@link PolicyMap} instance populated
114: * from information in WSIT config file. For more details on the whole process see
115: * {@link #parseModel(URL, boolean, PolicyMapMutator[]) parseModel}
116: * method.
117: *
118: * @param configFileUrl {@link URL} of the config file resource that should be parsed. Must not be {@code null}.
119: * @param isClient must be {@code true} if this method is invoked to parse client configuration, {@code false} otherwise
120: * @param mutators to be registered with the populated {@link PolicyMap} object. May be
121: * ommited if user does not plan to modify the {@link PolicyMap} instance.
122: *
123: * @return A {@link WSDLModel} with a {@link PolicyMap} object populated with information read
124: * from the WSIT config file.
125: * @throws PolicyException in case of any problems that may occur while reading WSIT config file
126: * and constructing the {@link WSDLModel} object or populating {@link PolicyMap} instance.
127: * @throws IllegalArgumentException in case {@code configFileUrl} parameter is {@code null}.
128: */
129: public static PolicyMap parse(final URL configFileUrl,
130: final boolean isClient, final PolicyMapMutator... mutators)
131: throws PolicyException, IllegalArgumentException {
132: LOGGER.entering(configFileUrl, isClient, mutators);
133: PolicyMap map = null;
134: try {
135: return map = extractPolicyMap(parseModel(configFileUrl,
136: isClient, mutators));
137: } finally {
138: LOGGER.exiting(map);
139: }
140: }
141:
142: /**
143: * Utility method that tries to retrieve a {@link PolicyMap} object from a given
144: * {@link WSDLModel}. When succesfull, {@link PolicyMap} instance is returned,
145: * otherwise result is {@code null}.
146: *
147: * @param model A {@link WSDLModel} (possibly) with a {@link PolicyMap} object
148: * populated with information read from the WSIT config file. May be {@code null};
149: * in that case, {@code null} is returned as a result of this function call.
150: *
151: * @return {@link PolicyMap} instance retrieved from a given {@link WSDLModel}
152: * if successful, {@code null} otherwise.
153: */
154: public static PolicyMap extractPolicyMap(final WSDLModel model) {
155: LOGGER.entering(model);
156: PolicyMap result = null;
157: try {
158: if (model != null) {
159: final WSDLPolicyMapWrapper wrapper = model
160: .getExtension(WSDLPolicyMapWrapper.class);
161:
162: if (wrapper != null) {
163: result = wrapper.getPolicyMap();
164: }
165: }
166: return result;
167: } finally {
168: LOGGER.exiting(result);
169: }
170: }
171:
172: /**
173: * The function uses {@code configFileIdentifier} parameter to construct a WSIT config
174: * file name according to following pattern:
175: * <p />
176: * <code>wsit-<i>[configFileIdentifier]</i>.xml</code>
177: * <p />
178: * After constructing the WSIT config file name, the function tries to find the WSIT
179: * config file and read it from the following locations:
180: * <ul>
181: * <li>{@code WEB-INF} - for servlet-based web service implementations</li>
182: * <li>{@code META-INF} - for EJB-based web service implementations</li>
183: * <li>{@code classpath} - for web service clients</li>
184: * </ul>
185: *
186: * If the file is found it is parsed and resulting {@link WSDLModel} object containig the
187: * populated {@link PolicyMap} instance is returned. If config file is not found, warning
188: * message is logged and {@code null} is returned as a result of this function call. In case
189: * of any other problems that may occur while reading the WSIT config file, a
190: * {@link PolicyException} is thrown.
191: * <p/>
192: * Since {@link PolicyMap} object is immutable as such, this function gives you also a chance
193: * to register your own {@link PolicyMapMutator} objects so that you are able to modify the
194: * {@link PolicyMap} object later if needed.
195: *
196: * @param configFileIdentifier base of WSIT config file name (web service name for WSIT service
197: * config file or "client" for WSIT client configuration). Must not be {@code null}.
198: * @param container if the application is run inside a web container, the container instance
199: * should be passed into this function, in order to get access to the servlet context
200: * that is used to load config file stored in {@code WEB-INF} directory of the application.
201: * May be {@code null}.
202: * @param mutators to be registered with the populated {@link PolicyMap} object. May be
203: * ommited if user does not plan to modify the {@link PolicyMap} instance.
204: *
205: * @return A {@link WSDLModel} with a {@link PolicyMap} object populated with information read
206: * from the WSIT config file.
207: * @throws PolicyException in case of any problems that may occur while reading WSIT config file
208: * and constructing the {@link WSDLModel} object or populating {@link PolicyMap} instance.
209: */
210: public static WSDLModel parseModel(
211: final String configFileIdentifier,
212: final Container container,
213: final PolicyMapMutator... mutators) throws PolicyException {
214: LOGGER.entering(configFileIdentifier, container, mutators);
215: WSDLModel model = null;
216: try {
217: final String configFileName = PolicyUtils.ConfigFile
218: .generateFullName(configFileIdentifier);
219: LOGGER.finest(LocalizationMessages
220: .WSP_1037_CONFIG_FILE_IS(configFileName));
221:
222: Object context = null;
223: if (container != null) {
224: try {
225: final Class<?> contextClass = Class
226: .forName(SERVLET_CONTEXT_CLASSNAME);
227: context = container.getSPI(contextClass);
228: } catch (ClassNotFoundException e) {
229: LOGGER
230: .fine(LocalizationMessages
231: .WSP_1043_CAN_NOT_FIND_CLASS(SERVLET_CONTEXT_CLASSNAME));
232: }
233: LOGGER.finest(LocalizationMessages
234: .WSP_1036_CONTEXT_IS(context));
235:
236: }
237:
238: URL configFileUrl = null;
239: final boolean isClientConfig = PolicyConstants.CLIENT_CONFIGURATION_IDENTIFIER
240: .equals(configFileIdentifier);
241: String examinedPath;
242: if (context == null || isClientConfig) {
243: examinedPath = JAR_PREFIX + configFileName;
244: configFileUrl = PolicyUtils.ConfigFile
245: .loadFromClasspath(examinedPath);
246: if (configFileUrl == null && isClientConfig) {
247: examinedPath = examinedPath + File.pathSeparator
248: + " " + configFileName;
249: configFileUrl = PolicyUtils.ConfigFile
250: .loadFromClasspath(configFileName);
251: }
252: } else {
253: examinedPath = WAR_PREFIX + configFileName;
254: configFileUrl = PolicyUtils.ConfigFile.loadFromContext(
255: examinedPath, context);
256: }
257:
258: if (configFileUrl == null) {
259: LOGGER.config(LocalizationMessages
260: .WSP_1035_COULD_NOT_LOCATE_WSIT_CFG_FILE(
261: configFileIdentifier, examinedPath));
262: } else {
263: model = parseModel(configFileUrl, isClientConfig,
264: mutators);
265: LOGGER.info(LocalizationMessages
266: .WSP_1049_LOADED_WSIT_CFG_FILE(configFileUrl
267: .toExternalForm()));
268: }
269:
270: return model;
271: } finally {
272: LOGGER.exiting(model);
273: }
274: }
275:
276: /**
277: * Reads the WSIT config from a file denoted by {@code configFileUrl} parameter.
278: * If the file exists it is parsed and resulting {@link WSDLModel} object containig the
279: * populated {@link PolicyMap} instance is returned. If config file for given {@link URL}
280: * does not exist or in case of any other problems that may occur while reading the
281: * WSIT config file, a {@link PolicyException} is thrown.
282: *
283: * @param configFileUrl {@link URL} of the config file resource that should be parsed. Must not be {@code null}.
284: * @param isClient must be {@code true} if this method is invoked to parse client configuration, {@code false} otherwise
285: * @param mutators to be registered with the populated {@link PolicyMap} object. May be
286: * ommited if user does not plan to modify the {@link PolicyMap} instance.
287: *
288: * @return A {@link WSDLModel} with a {@link PolicyMap} object populated with information read
289: * from the WSIT config file.
290: * @throws PolicyException in case of any problems that may occur while reading WSIT config file
291: * and constructing the {@link WSDLModel} object or populating {@link PolicyMap} instance.
292: * @throws IllegalArgumentException in case {@code configFileUrl} parameter is {@code null}.
293: */
294: public static WSDLModel parseModel(final URL configFileUrl,
295: final boolean isClient, final PolicyMapMutator... mutators)
296: throws PolicyException, IllegalArgumentException {
297: LOGGER.entering(configFileUrl, isClient, mutators);
298: WSDLModel model = null;
299: try {
300: if (null == configFileUrl) {
301: throw LOGGER
302: .logSevereException(new IllegalArgumentException(
303: LocalizationMessages
304: .WSP_1028_FAILED_TO_READ_NULL_WSIT_CFG()));
305: }
306:
307: final SDDocumentSource doc = SDDocumentSource
308: .create(configFileUrl);
309: final XMLEntityResolver.Parser parser = new XMLEntityResolver.Parser(
310: doc);
311: model = WSDLModel.WSDLParser
312: .parse(
313: parser,
314: new PolicyConfigResolver(),
315: isClient,
316: new WSDLParserExtension[] { new PolicyWSDLParserExtension(
317: true, mutators) });
318:
319: return model;
320: } catch (XMLStreamException ex) {
321: throw LOGGER
322: .logSevereException(new PolicyException(
323: LocalizationMessages
324: .WSP_1002_WSIT_CFG_FILE_PROCESSING_FAILED(configFileUrl
325: .toString()), ex));
326: } catch (IOException ex) {
327: throw LOGGER
328: .logSevereException(new PolicyException(
329: LocalizationMessages
330: .WSP_1002_WSIT_CFG_FILE_PROCESSING_FAILED(configFileUrl
331: .toString()), ex));
332: } catch (SAXException ex) {
333: throw LOGGER
334: .logSevereException(new PolicyException(
335: LocalizationMessages
336: .WSP_1002_WSIT_CFG_FILE_PROCESSING_FAILED(configFileUrl
337: .toString()), ex));
338: } finally {
339: LOGGER.exiting(model);
340: }
341: }
342: }
|