blob: 2b6855fc3f836d4abe1b05d310f1da1f8fe09dd9 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.netbeans.modules.j2ee.dd.api.webservices;
import java.io.IOException;
import java.io.InputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.netbeans.modules.j2ee.dd.impl.webservices.WebServicesProxy;
import org.netbeans.modules.schema2beans.Common;
import org.openide.filesystems.*;
import org.xml.sax.*;
import java.util.Map;
import org.w3c.dom.Document;
public final class DDProvider {
private static final DDProvider ddProvider = new DDProvider();
private Map ddMap;
/** Creates a new instance of WebSvcModule */
private DDProvider() {
//ddMap=new java.util.WeakHashMap(5);
ddMap = new java.util.HashMap(5);
}
/**
* Accessor method for DDProvider singleton
* @return DDProvider object
*/
public static DDProvider getDefault() {
return ddProvider;
}
/**
* Returns the root of deployment descriptor bean graph for given file object.
* The method is useful for clints planning to read only the deployment descriptor
* or to listen to the changes.
* @param fo FileObject representing the xml file
* @return Webservices object - root of the deployment descriptor bean graph
*/
public synchronized Webservices getDDRoot(FileObject fo) throws java.io.IOException {
if(fo == null) return null;
WebServicesProxy webSvcProxy = getFromCache (fo);
if (webSvcProxy!=null) {
return webSvcProxy;
}
fo.addFileChangeListener(new FileChangeAdapter() {
public void fileChanged(FileEvent evt) {
FileObject fo=evt.getFile();
try {
WebServicesProxy webSvcProxy = getFromCache (fo);
String version = null;
if (webSvcProxy!=null) {
try {
DDParse parseResult = parseDD(fo);
version = parseResult.getVersion();
setProxyErrorStatus(webSvcProxy, parseResult);
Webservices newValue = createWebSvcJar(parseResult);
// replacing original file in proxy Webservices
if (!version.equals(webSvcProxy.getVersion().toString())) {
webSvcProxy.setOriginal(newValue);
} else {// the same version
// replacing original file in proxy Webservices
if (webSvcProxy.getOriginal()==null) {
webSvcProxy.setOriginal(newValue);
} else {
webSvcProxy.getOriginal().merge(newValue,Webservices.MERGE_UPDATE);
}
}
} catch (SAXException ex) {
if (ex instanceof SAXParseException) {
webSvcProxy.setError((SAXParseException)ex);
} else if ( ex.getException() instanceof SAXParseException) {
webSvcProxy.setError((SAXParseException)ex.getException());
}
webSvcProxy.setStatus(Webservices.STATE_INVALID_UNPARSABLE);
// cbw if the state of the xml file transitions from
// parsable to unparsable this could be due to a user
// change or cvs change. We would like to still
// receive events when the file is restored to normal
// so lets not set the original to null here but wait
// until the file becomes parsable again to do a merge
//webSvcProxy.setOriginal(null);
webSvcProxy.setProxyVersion(Webservices.VERSION_1_1);
}
}
} catch (java.io.IOException ex){}
}
});
try {
DDParse parseResult = parseDD(fo);
Webservices original = createWebSvcJar(parseResult);
webSvcProxy = new WebServicesProxy(original,parseResult.getVersion());
setProxyErrorStatus(webSvcProxy, parseResult);
} catch (SAXException ex) {
// XXX lets throw an exception here
webSvcProxy = new WebServicesProxy(org.netbeans.modules.j2ee.dd.impl.webservices.model_1_2.Webservices.createGraph(),"1.2");
webSvcProxy.setStatus(Webservices.STATE_INVALID_UNPARSABLE);
if (ex instanceof SAXParseException) {
webSvcProxy.setError((SAXParseException)ex);
} else if ( ex.getException() instanceof SAXParseException) {
webSvcProxy.setError((SAXParseException)ex.getException());
}
}
ddMap.put(fo, /*new WeakReference*/ (webSvcProxy));
return webSvcProxy;
}
/**
* Returns the root of deployment descriptor bean graph for given file object.
* The method is useful for clients planning to modify the deployment descriptor.
* Finally the {@link org.netbeans.modules.j2ee.dd.impl.webservices.model_1_1.Webservices#write(org.openide.filesystems.FileObject)} should be used
* for writing the changes.
* @param fo FileObject representing the xml file
* @return Webservices object - root of the deployment descriptor bean graph
*/
public Webservices getDDRootCopy(FileObject fo) throws java.io.IOException {
return (Webservices)getDDRoot(fo).clone();
}
private WebServicesProxy getFromCache (FileObject fo) {
return (WebServicesProxy) ddMap.get(fo);
}
/**
* Returns the root of deployment descriptor bean graph for java.io.File object.
*
* @param is source representing the xml file
* @return Webservices object - root of the deployment descriptor bean graph
*/
public Webservices getDDRoot(InputSource is) throws IOException, SAXException {
DDParse parse = parseDD(is);
Webservices webSvcJar = createWebSvcJar(parse);
WebServicesProxy proxy = new WebServicesProxy(webSvcJar, webSvcJar.getVersion().toString());
setProxyErrorStatus(proxy, parse);
return proxy;
}
// PENDING j2eeserver needs BaseBean - this is a temporary workaround to avoid dependency of web project on DD impl
/** Convenient method for getting the BaseBean object from CommonDDBean object
* @deprecated DO NOT USE - TEMPORARY WORKAROUND !!!!
*/
public org.netbeans.modules.schema2beans.BaseBean getBaseBean(org.netbeans.modules.j2ee.dd.api.common.CommonDDBean bean) {
if (bean instanceof org.netbeans.modules.schema2beans.BaseBean) return (org.netbeans.modules.schema2beans.BaseBean)bean;
else if (bean instanceof WebServicesProxy) return (org.netbeans.modules.schema2beans.BaseBean) ((WebServicesProxy)bean).getOriginal();
return null;
}
private static void setProxyErrorStatus(WebServicesProxy webSvcProxy, DDParse parse) {
SAXParseException error = parse.getWarning();
webSvcProxy.setError(error);
if (error!=null) {
webSvcProxy.setStatus(Webservices.STATE_INVALID_PARSABLE);
} else {
webSvcProxy.setStatus(Webservices.STATE_VALID);
}
}
private static Webservices createWebSvcJar(DDParse parse) throws SAXException{
Webservices jar = null;
String version = parse.getVersion();
if (Webservices.VERSION_1_1.equals(version)) {
try {
return new org.netbeans.modules.j2ee.dd.impl.webservices.model_1_1.Webservices(parse.getDocument(), Common.USE_DEFAULT_VALUES);
} catch (RuntimeException ex) {
throw new SAXException(ex.getMessage());
}
} else if (Webservices.VERSION_1_2.equals(version)) {
try {
return new org.netbeans.modules.j2ee.dd.impl.webservices.model_1_2.Webservices(parse.getDocument(), Common.USE_DEFAULT_VALUES);
} catch (RuntimeException ex) {
throw new SAXException(ex.getMessage());
}
}
return jar;
}
private static class DDResolver implements EntityResolver {
static DDResolver resolver;
static synchronized DDResolver getInstance() {
if (resolver==null) {
resolver=new DDResolver();
}
return resolver;
}
public InputSource resolveEntity (String publicId, String systemId) {
if ("http://www.ibm.com/webservices/xsd/j2ee_web_services_1_1.xsd".equals(systemId)) {
return new InputSource("nbres:/org/netbeans/modules/j2ee/dd/impl/resources/j2ee_web_services_1_1.xsd"); //NOI18N
} else if ("http://java.sun.com/xml/ns/j2ee/j2ee_web_services_1_1.xsd".equals(systemId)) {
return new InputSource("nbres:/org/netbeans/modules/j2ee/dd/impl/resources/j2ee_web_services_1_1.xsd"); //NOI18N
} else if ("http://www.ibm.com/webservices/xsd/javaee_web_services_1_2.xsd".equals(systemId)) {
return new InputSource("nbres:/org/netbeans/modules/j2ee/dd/impl/resources/javaee_web_services_1_2.xsd"); //NOI18N
} else if ("http://java.sun.com/xml/ns/j2ee/javaee_web_services_1_2.xsd".equals(systemId)) {
return new InputSource("nbres:/org/netbeans/modules/j2ee/dd/impl/resources/javaee_web_services_1_2.xsd"); //NOI18N
} else {
// use the default behaviour
return null;
}
}
}
private static class ErrorHandler implements org.xml.sax.ErrorHandler {
private int errorType=-1;
SAXParseException error;
public void warning(org.xml.sax.SAXParseException sAXParseException) throws org.xml.sax.SAXException {
if (errorType<0) {
errorType=0;
error=sAXParseException;
}
//throw sAXParseException;
}
public void error(org.xml.sax.SAXParseException sAXParseException) throws org.xml.sax.SAXException {
if (errorType<1) {
errorType=1;
error=sAXParseException;
}
//throw sAXParseException;
}
public void fatalError(org.xml.sax.SAXParseException sAXParseException) throws org.xml.sax.SAXException {
errorType=2;
throw sAXParseException;
}
public int getErrorType() {
return errorType;
}
public SAXParseException getError() {
return error;
}
}
public SAXParseException parse(FileObject fo)
throws org.xml.sax.SAXException, java.io.IOException {
DDParse parseResult = parseDD(fo);
return parseResult.getWarning();
}
private DDParse parseDD (FileObject fo)
throws SAXException, java.io.IOException {
return parseDD(fo.getInputStream());
}
private DDParse parseDD (InputStream is)
throws SAXException, java.io.IOException {
return parseDD(new InputSource(is));
}
private DDParse parseDD (InputSource is)
throws SAXException, java.io.IOException {
DDProvider.ErrorHandler errorHandler = new DDProvider.ErrorHandler();
DocumentBuilder parser=null;
try {
DocumentBuilderFactory fact = DocumentBuilderFactory.newInstance();
parser = fact.newDocumentBuilder();
} catch (ParserConfigurationException ex) {
throw new SAXException(ex.getMessage());
}
parser.setErrorHandler(errorHandler);
parser.setEntityResolver(DDProvider.DDResolver.getInstance());
Document d = parser.parse(is);
SAXParseException error = errorHandler.getError();
return new DDParse(d, error);
}
/**
* This class represents one parse of the deployment descriptor
*/
private static class DDParse {
private Document document;
private SAXParseException saxException;
private String version;
public DDParse(Document d, SAXParseException saxEx) {
document = d;
saxException = saxEx;
extractVersion();
}
/**
* @return document from last parse
*/
public Document getDocument() {
return document;
}
/**
* @return version of deployment descriptor.
*/
private void extractVersion () {
// This is the default version
String ver = document.getDocumentElement().getAttribute("version"); //NOI18N
version = (Webservices.VERSION_1_1.equals(ver))?Webservices.VERSION_1_1:Webservices.VERSION_1_2;
}
public String getVersion() {
return version;
}
/**
* @return validation error encountered during the parse
*/
public SAXParseException getWarning() {
return saxException;
}
}
}