| /******************************************************************************* |
| * Copyright (c) 2005 IBM Corporation and others. |
| * All rights reserved. This program and the accompanying materials |
| * are made available under the terms of the Eclipse Public License v1.0 |
| * which accompanies this distribution, and is available at |
| * http://www.eclipse.org/legal/epl-v10.html |
| * |
| * Contributors: |
| * IBM Corporation - initial API and implementation |
| *******************************************************************************/ |
| package org.eclipse.bpel.model.resource; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.io.OutputStream; |
| import java.util.ArrayList; |
| import java.util.List; |
| import java.util.Map; |
| import javax.xml.namespace.QName; |
| import javax.xml.parsers.DocumentBuilder; |
| import javax.xml.parsers.DocumentBuilderFactory; |
| import javax.xml.parsers.ParserConfigurationException; |
| |
| import org.apache.xerces.parsers.DOMParser; |
| import org.apache.xerces.xni.Augmentations; |
| import org.apache.xerces.xni.NamespaceContext; |
| import org.apache.xerces.xni.XMLAttributes; |
| import org.apache.xerces.xni.XMLLocator; |
| import org.apache.xerces.xni.XMLString; |
| import org.apache.xerces.xni.XNIException; |
| import org.eclipse.bpel.model.Import; |
| import org.eclipse.bpel.model.Process; |
| import org.eclipse.bpel.model.adapters.INamespaceMap; |
| import org.eclipse.bpel.model.util.BPELConstants; |
| import org.eclipse.bpel.model.util.BPELProxyURI; |
| import org.eclipse.bpel.model.util.BPELUtils; |
| import org.eclipse.bpel.model.util.ImportResolver; |
| import org.eclipse.bpel.model.util.ImportResolverRegistry; |
| import org.eclipse.emf.common.util.URI; |
| import org.eclipse.emf.ecore.EObject; |
| import org.eclipse.emf.ecore.xmi.impl.XMLResourceImpl; |
| import org.eclipse.wst.wsdl.Definition; |
| import org.eclipse.xsd.XSDSchema; |
| import org.eclipse.xsd.impl.XSDSchemaImpl; |
| import org.eclipse.xsd.util.XSDConstants; |
| import org.w3c.dom.Document; |
| import org.w3c.dom.Element; |
| import org.xml.sax.EntityResolver; |
| import org.xml.sax.ErrorHandler; |
| |
| |
| public class BPELResourceImpl extends XMLResourceImpl implements BPELResource { |
| protected static boolean USE_IMPORTS = false; |
| |
| /** @see #getNamespaceURI() */ |
| private String processNamespaceURI = BPELConstants.NAMESPACE; |
| |
| /** @see #getOptionUseNSPrefix() */ |
| private boolean optionUseNSPrefix = true; |
| |
| // Properties for validating bpel document |
| protected boolean validating = false; |
| protected EntityResolver entityResolver = null; |
| protected ErrorHandler errorHandler = null; |
| |
| public BPELResourceImpl() { |
| super(); |
| } |
| |
| public BPELResourceImpl(URI arg0) { |
| super(arg0); |
| } |
| |
| public BPELResourceImpl(URI uri, EntityResolver entityResolver, ErrorHandler errorHandler) throws IOException { |
| super(uri); |
| this.entityResolver = entityResolver; |
| this.errorHandler = errorHandler; |
| validating = true; |
| } |
| |
| // Bugzilla 324165 |
| public void setErrorHandler(ErrorHandler errorHandler) |
| { |
| this.errorHandler = errorHandler; |
| validating = true; |
| } |
| |
| // Bugzilla 324165 |
| public ErrorHandler getErrorHandler() |
| { |
| return errorHandler; |
| } |
| |
| /** |
| * Convert the BPEL model to an XML DOM model and then write the DOM model |
| * to the output stream. |
| */ |
| @Override |
| public void doSave(OutputStream out, Map<?, ?> args) throws IOException |
| { |
| INamespaceMap<String, String> nsMap = BPELUtils.getNamespaceMap(this.getProcess()); |
| if (getOptionUseNSPrefix()) { |
| nsMap.remove(""); |
| List<String> prefix = nsMap.getReverse(getNamespaceURI()); |
| if (prefix.isEmpty()){ |
| nsMap.put(BPELConstants.PREFIX, getNamespaceURI()); |
| } |
| } else { |
| nsMap.put("", getNamespaceURI()); |
| } |
| |
| // RTP: resolver = new Resolver(this); |
| |
| BPELWriter writer = new BPELWriter(); |
| writer.write(this, out, args); |
| } |
| |
| /** |
| * Convert a BPEL XML document into the BPEL EMF model. |
| * After loading, the process' checks for process type (executable/abstract) |
| * and resets the current namespace accordingly. If the process type is abstract |
| * and no profile has been set, the default abstract process profile is being inserted. |
| * |
| */ |
| @Override |
| public void doLoad(InputStream inputStream, Map<?, ?> options) throws IOException |
| { |
| // getPrefixToNamespaceMap().put("", BPELConstants.NAMESPACE); |
| |
| // RTP: resolver = new Resolver(this); |
| |
| // BPELReader reader = new BPELReader(getDocumentBuilder()); |
| |
| BPELReader reader = null; |
| Document document = null; |
| |
| if (options != null |
| && (document = (org.w3c.dom.Document)options.get("DOMDocument")) != null) { |
| reader = new BPELReader(); |
| reader.read(this, document); |
| |
| } else { |
| try { |
| reader = new BPELReader( getDOMParser() ); |
| } catch (IOException ioe) { |
| throw ioe; |
| } catch (Exception ex) { |
| throw new IOException("Problem create parser"); |
| } |
| reader.read(this, inputStream); |
| } |
| |
| //Check for process type Abstract/ Executable |
| Element processElement = (document != null)? document.getDocumentElement(): null; |
| if (processElement != null && reader.isAbstractProcess(processElement)) |
| { |
| setNamespaceURI(BPELConstants.NAMESPACE_ABSTRACT_2007); |
| //TODO: Let user decide whether to use a profile |
| if (reader.getProfileNamespace(processElement) != null){ |
| getProcess().setAbstractProcessProfile(reader.getProfileNamespace(processElement)); |
| } else { |
| getProcess().setAbstractProcessProfile(BPELConstants.NAMESPACE_ABSTRACT_PROFILE); |
| } |
| } else { |
| setNamespaceURI(BPELConstants.NAMESPACE); |
| } |
| |
| boolean usePrefix = |
| checkUseNSPrefix(BPELConstants.NAMESPACE_2004) || |
| checkUseNSPrefix(BPELConstants.NAMESPACE_2007) || |
| checkUseNSPrefix(BPELConstants.NAMESPACE_ABSTRACT_2007); |
| this.setOptionUseNSPrefix(usePrefix); |
| } |
| |
| private boolean checkUseNSPrefix(String bpelNamespace) { |
| INamespaceMap<String, String> nsMap = BPELUtils.getNamespaceMap(getProcess()); |
| List<String> prefixes; |
| prefixes = nsMap.getReverse(bpelNamespace); |
| for (int i=0; i<prefixes.size(); ++i) { |
| String ns = prefixes.get(i); |
| if (ns!=null && !ns.equals("")) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| /* |
| * TODO Implement getURIFragment to return our encoding. |
| */ |
| @Override |
| public String getURIFragment(EObject eObject) |
| { |
| return super.getURIFragment(eObject); |
| } |
| |
| /** |
| * Find and return the EObject represented by the given uriFragment. |
| * |
| * @return the resolved EObject or null if none could be found. |
| */ |
| @Override |
| public EObject getEObject(String uriFragment) { |
| if (uriFragment == null) return null; |
| try { |
| // Consult the superclass |
| EObject eObject = super.getEObject(uriFragment); |
| if (eObject != null) return eObject; |
| // Consult our helper method |
| eObject = getEObjectExtended(uriFragment); |
| if (eObject != null) return eObject; |
| return null; |
| } catch (RuntimeException e) { |
| // TODO: Should log this instead of printing to stderr. |
| // e.printStackTrace(); |
| throw e; |
| } |
| } |
| |
| /** |
| * Helper method for resolving the EObject. |
| * |
| */ |
| protected EObject getEObjectExtended(String uriFragment) |
| { |
| // RTP: this implementation should be extensible |
| |
| BPELProxyURI proxyURI = new BPELProxyURI(uriFragment); |
| |
| QName qname = proxyURI.getQName(); |
| String typeName = proxyURI.getTypeName(); |
| |
| if (qname == null || typeName == null) { |
| return null; |
| } |
| |
| EObject result = null; |
| |
| // Try the BPEL imports if any exist. |
| Process process = getProcess(); |
| if (process == null) { |
| return result; |
| } |
| |
| |
| for (Import imp : process.getImports()){ |
| // The null and "" problem ... |
| String ns = imp.getNamespace(); |
| if (ns == null) { |
| ns = javax.xml.XMLConstants.DEFAULT_NS_PREFIX; |
| } |
| |
| if (ns.equals(qname.getNamespaceURI()) == false || |
| imp.getLocation() == null ) { |
| continue; |
| } |
| |
| for (ImportResolver r : ImportResolverRegistry.INSTANCE.getResolvers(imp.getImportType())){ |
| result = r.resolve(imp, qname, proxyURI.getID(), proxyURI.getTypeName()); |
| if (result != null) { |
| return result; |
| } |
| } |
| } |
| |
| // Failed to resolve. |
| return result; |
| } |
| |
| |
| |
| /** |
| * Return the list of schemas that are imported in this BPEL resource. |
| * This includes XSD imports and schemas present in WSDLs as well. |
| * |
| * @param bIncludeXSD whether the XSD standard schemas ought to be included |
| * regardless of import. |
| * |
| * @return a list of XSDScheme objects |
| */ |
| public List<XSDSchema> getSchemas ( boolean bIncludeXSD ) |
| { |
| ArrayList<XSDSchema> al = new ArrayList<XSDSchema>(8); |
| |
| // Try the BPEL imports if any exist. |
| Process process = getProcess(); |
| if (process == null) { |
| return al; |
| } |
| |
| for (Import imp : process.getImports()) { |
| if (imp.getLocation() == null ) { |
| continue; |
| } |
| for(ImportResolver r : ImportResolverRegistry.INSTANCE.getResolvers(imp.getImportType())) { |
| al.addAll( (List<? extends XSDSchema>) r.resolve (imp, ImportResolver.RESOLVE_SCHEMA ) ); |
| } |
| } |
| |
| if (bIncludeXSD) { |
| al.add ( XSDSchemaImpl.getSchemaForSchema( XSDConstants.SCHEMA_FOR_SCHEMA_URI_2001 ) ); |
| } |
| |
| return al; |
| } |
| |
| |
| /** |
| * Get the definitions that are included in this BPEL (via the WSDL imports) |
| * |
| * @return |
| */ |
| |
| public List<Definition> getDefinitions () { |
| ArrayList<Definition> al = new ArrayList<Definition>(8); |
| |
| // Try the BPEL imports if any exist. |
| Process process = getProcess(); |
| if (process == null) { |
| return al; |
| } |
| |
| for (Import imp : process.getImports()) { |
| if (imp.getLocation() == null ) { |
| continue; |
| } |
| for(ImportResolver r : ImportResolverRegistry.INSTANCE.getResolvers(imp.getImportType())) { |
| al.addAll( (List<? extends Definition>) r.resolve (imp, ImportResolver.RESOLVE_DEFINITION ) ); |
| } |
| } |
| |
| return al; |
| } |
| |
| public Process getProcess() { |
| return getContents().size() == 1 && getContents().get(0) instanceof Process ? (Process) getContents().get(0) : null; |
| } |
| |
| protected DocumentBuilder getDocumentBuilder() throws IOException { |
| final DocumentBuilderFactory factory = //DocumentBuilderFactory.newInstance(); |
| // new org.apache.crimson.jaxp.DocumentBuilderFactoryImpl(); |
| new org.apache.xerces.jaxp.DocumentBuilderFactoryImpl(); |
| |
| if (validating && factory.getClass().getName().indexOf("org.apache.xerces") != -1) |
| { |
| // Note: This section is subject to change as this issue will be |
| // addressed in a maintenance release of JSR-63. |
| // Hopefully this will be a proper API in JAXP 1.2! |
| // turn dynamic schema validation on |
| factory.setAttribute("http://apache.org/xml/features/validation/dynamic", Boolean.TRUE); |
| // turn schema validation on |
| factory.setAttribute("http://apache.org/xml/features/validation/schema", Boolean.TRUE); |
| // set the default schemaLocation for syntactical validation |
| factory.setAttribute("http://apache.org/xml/properties/schema/external-schemaLocation", |
| BPELConstants.NAMESPACE); |
| } |
| |
| factory.setIgnoringComments(true); |
| factory.setIgnoringElementContentWhitespace(true); |
| |
| factory.setValidating(validating); |
| factory.setNamespaceAware(true); |
| |
| DocumentBuilder builder; |
| try { |
| builder = factory.newDocumentBuilder(); |
| } catch (ParserConfigurationException exc) { |
| // exc.printStackTrace(); |
| throw new IOException(exc.toString()); |
| } |
| if (validating) { |
| builder.setEntityResolver( entityResolver ); |
| builder.setErrorHandler( errorHandler ); |
| } |
| |
| return builder; |
| } |
| |
| |
| |
| |
| @SuppressWarnings({ "nls", "boxing" }) |
| protected DOMParser getDOMParser() throws Exception { |
| |
| // This is per |
| // http://src.opensolaris.org/source/xref/sfw/usr/src/cmd/tomcat/xerces-2_8_0/samples/dom/DOMAddLines.java |
| // |
| DOMParser domParser = new DOMParser () { |
| |
| protected XMLLocator mLocator; |
| |
| protected int fLineNo = 0; |
| protected int fColumnNo = 0; |
| protected int fOffset = 0; |
| |
| void lastSource () { |
| |
| fLineNo = mLocator.getLineNumber(); |
| fColumnNo = mLocator.getColumnNumber(); |
| fOffset = mLocator.getCharacterOffset() ; |
| |
| // p(" - lastSource.mark : r={0},c={1},o={2}",fLineNo, fColumnNo,fOffset ); |
| } |
| |
| /** |
| * @see org.apache.xerces.parsers.AbstractDOMParser#startDocument(org.apache.xerces.xni.XMLLocator, java.lang.String, org.apache.xerces.xni.NamespaceContext, org.apache.xerces.xni.Augmentations) |
| */ |
| @Override |
| public void startDocument(XMLLocator arg0, String arg1, NamespaceContext arg2, Augmentations arg3) throws XNIException { |
| mLocator = arg0; |
| super.startDocument(arg0, arg1, arg2, arg3); |
| lastSource(); |
| } |
| |
| |
| |
| |
| /** |
| * @see org.apache.xerces.parsers.AbstractDOMParser#characters(org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations) |
| */ |
| @Override |
| public void characters(XMLString arg0, Augmentations arg1) throws XNIException { |
| super.characters(arg0, arg1); |
| lastSource(); |
| } |
| |
| |
| |
| |
| /** |
| * @see org.apache.xerces.parsers.AbstractDOMParser#comment(org.apache.xerces.xni.XMLString, org.apache.xerces.xni.Augmentations) |
| */ |
| @Override |
| public void comment(XMLString arg0, Augmentations arg1) throws XNIException { |
| super.comment(arg0, arg1); |
| lastSource(); |
| |
| } |
| |
| |
| |
| /* (non-Javadoc) |
| * @see org.apache.xerces.parsers.AbstractDOMParser#textDecl(java.lang.String, java.lang.String, org.apache.xerces.xni.Augmentations) |
| */ |
| @Override |
| public void textDecl(String arg0, String arg1, Augmentations arg2) throws XNIException { |
| super.textDecl(arg0, arg1, arg2); |
| lastSource(); |
| } |
| |
| |
| |
| /** |
| * @see org.apache.xerces.parsers.AbstractDOMParser#startElement(org.apache.xerces.xni.QName, org.apache.xerces.xni.XMLAttributes, org.apache.xerces.xni.Augmentations) |
| */ |
| @Override |
| public void startElement (org.apache.xerces.xni.QName arg0, XMLAttributes arg1, Augmentations arg2) throws XNIException { |
| super.startElement(arg0, arg1, arg2); |
| // p("startElement: {0} {1}", arg0,arg1); |
| |
| if (fCurrentNode != null) { |
| // p(" - start.mark: r={0},c={1},o={2}",fLineNo,fColumnNo,fOffset+1); |
| // start of element |
| fCurrentNode.setUserData("location.line", fLineNo, null); |
| fCurrentNode.setUserData("location.column", fColumnNo, null); |
| fCurrentNode.setUserData("location.charStart", fOffset+1, null); |
| fCurrentNode.setUserData("location.charEnd", fOffset + arg0.rawname.length()+1 , null); |
| |
| // p(" - end.mark: r={0},c={1},o={2}",mLocator.getLineNumber(), mLocator.getColumnNumber(),mLocator.getCharacterOffset() ); |
| // end of element |
| fCurrentNode.setUserData("location2.line", mLocator.getLineNumber(), null); |
| fCurrentNode.setUserData("location2.column", mLocator.getColumnNumber(), null); |
| fCurrentNode.setUserData("location2.charStart", mLocator.getCharacterOffset(), null); |
| fCurrentNode.setUserData("location2.charEnd", mLocator.getCharacterOffset(), null); |
| } |
| lastSource(); |
| } |
| |
| |
| @Override |
| public void startCDATA( Augmentations aug ) { |
| super.startCDATA(aug); |
| lastSource(); |
| |
| } |
| |
| @Override |
| public void endCDATA( Augmentations aug ) { |
| super.endCDATA(aug); |
| lastSource(); |
| } |
| |
| @Override |
| public void endElement ( org.apache.xerces.xni.QName element, Augmentations aug ) { |
| super.endElement(element, aug); |
| // p("endElement: {0}", element); |
| lastSource(); |
| } |
| |
| // void p ( String fmt, Object ... args) { |
| // System.out.println(java.text.MessageFormat.format(fmt,args)); |
| // } |
| |
| }; |
| |
| |
| |
| |
| if (validating) |
| { |
| // Note: This section is subject to change as this issue will be |
| // addressed in a maintenance release of JSR-63. |
| // Hopefully this will be a proper API in JAXP 1.2! |
| // turn dynamic schema validation on |
| domParser.setFeature("http://apache.org/xml/features/validation/dynamic", Boolean.TRUE); |
| // turn schema validation on |
| domParser.setFeature("http://apache.org/xml/features/validation/schema", Boolean.TRUE); |
| // set the default schemaLocation for syntactical validation |
| domParser.setProperty("http://apache.org/xml/properties/schema/external-schemaLocation", |
| BPELConstants.NAMESPACE); |
| } |
| |
| // domParser.setProperty("http://xml.org/sax/features/namespaces",true); |
| domParser.setFeature( "http://apache.org/xml/features/dom/defer-node-expansion", false ); |
| domParser.setFeature( "http://apache.org/xml/features/xinclude", false); |
| |
| if (validating) { |
| domParser.setEntityResolver( entityResolver ); |
| domParser.setErrorHandler( errorHandler ); |
| } |
| |
| return domParser; |
| } |
| |
| |
| public static void setUseImports(boolean useImports) { |
| USE_IMPORTS = useImports; |
| } |
| |
| public String getNamespaceURI() { |
| return processNamespaceURI; |
| } |
| |
| public void setNamespaceURI(String namespaceURI) { |
| processNamespaceURI = namespaceURI; |
| } |
| |
| public boolean getOptionUseNSPrefix() { |
| return optionUseNSPrefix; |
| } |
| |
| public void setOptionUseNSPrefix(boolean useNSPrefix) { |
| optionUseNSPrefix = useNSPrefix; |
| } |
| } |