/* * 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.apache.tuscany.sca.policy.xml; import static org.apache.tuscany.sca.policy.xml.PolicyConstants.SCA11_NS; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.StringTokenizer; import javax.xml.XMLConstants; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.stream.XMLStreamWriter; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathExpression; import javax.xml.xpath.XPathExpressionException; import org.apache.tuscany.sca.common.xml.xpath.XPathHelper; import org.apache.tuscany.sca.contribution.processor.BaseStAXArtifactProcessor; import org.apache.tuscany.sca.contribution.processor.ContributionReadException; import org.apache.tuscany.sca.contribution.processor.ContributionResolveException; import org.apache.tuscany.sca.contribution.processor.ContributionWriteException; import org.apache.tuscany.sca.contribution.processor.ProcessorContext; import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor; import org.apache.tuscany.sca.contribution.resolver.ModelResolver; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; import org.apache.tuscany.sca.monitor.Monitor; import org.apache.tuscany.sca.monitor.Problem; import org.apache.tuscany.sca.monitor.Problem.Severity; import org.apache.tuscany.sca.policy.ExternalAttachment; import org.apache.tuscany.sca.policy.Intent; import org.apache.tuscany.sca.policy.PolicyFactory; import org.apache.tuscany.sca.policy.PolicySet; /** * Processor for handling XML models of ExternalAttachment definitions * * @version $Rev: 961010 $ $Date: 2010-07-06 13:34:54 -0700 (Tue, 06 Jul 2010) $ */ public class ExternalAttachmentProcessor extends BaseStAXArtifactProcessor implements StAXArtifactProcessor<ExternalAttachment>, PolicyConstants { private PolicyFactory policyFactory; private XPathHelper xpathHelper; public ExternalAttachmentProcessor(ExtensionPointRegistry registry) { FactoryExtensionPoint factories = registry.getExtensionPoint(FactoryExtensionPoint.class); this.policyFactory = factories.getFactory(PolicyFactory.class); this.xpathHelper = XPathHelper.getInstance(registry); } public Class<ExternalAttachment> getModelType() { return ExternalAttachment.class; } public void resolve(ExternalAttachment attachment, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { if (attachment != null && attachment.isUnresolved()) { resolveIntents(attachment, resolver, context); resolvePolicySets(attachment, resolver, context); attachment.setUnresolved(false); } } private void resolvePolicySets(ExternalAttachment attachment, ModelResolver resolver, ProcessorContext context) { List<PolicySet> referredPolicySets = new ArrayList<PolicySet>(); for (PolicySet referredPolicySet : attachment.getPolicySets()) { if (referredPolicySet.isUnresolved()) { PolicySet resolved = resolver.resolveModel(PolicySet.class, referredPolicySet, context); if (!resolved.isUnresolved() || resolved != referredPolicySet) { referredPolicySets.add(resolved); } else { error(context.getMonitor(), "ReferredPolicySetNotFound", attachment, referredPolicySet, attachment); return; } } else { referredPolicySets.add(referredPolicySet); } } attachment.getPolicySets().clear(); attachment.getPolicySets().addAll(referredPolicySets); } private void resolveIntents(ExternalAttachment attachment, ModelResolver resolver, ProcessorContext context) { if (attachment != null) { //resolve all provided intents List<Intent> providedIntents = new ArrayList<Intent>(); for (Intent providedIntent : attachment.getIntents()) { if (providedIntent.isUnresolved()) { Intent resolved = resolver.resolveModel(Intent.class, providedIntent, context); if (!resolved.isUnresolved() || resolved != providedIntent) { providedIntents.add(resolved); } else { error(context.getMonitor(), "ProvidedIntentNotFound", attachment, providedIntent, attachment); return; } } else { providedIntents.add(providedIntent); } } attachment.getIntents().clear(); attachment.getIntents().addAll(providedIntents); } } public QName getArtifactType() { return EXTERNAL_ATTACHMENT_QNAME; } public ExternalAttachment read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { ExternalAttachment attachment = policyFactory.createExternalAttachment(); readPolicySets(attachment, reader); readIntents(attachment, reader, context); readAttachTo(attachment, reader, context); return attachment; } private void readIntents(ExternalAttachment attachment, XMLStreamReader reader, ProcessorContext context) { String value = reader.getAttributeValue(null, INTENTS); if (value != null) { List<Intent> intents = attachment.getIntents(); for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { QName qname = getQNameValue(reader, tokens.nextToken()); Intent intent = policyFactory.createIntent(); intent.setName(qname); intents.add(intent); } } } private void readAttachTo(ExternalAttachment attachment, XMLStreamReader reader, ProcessorContext context) { Monitor monitor = context.getMonitor(); String attachTo = reader.getAttributeValue(null, ATTACH_TO); if ( attachTo != null ) { try { XPath path = xpathHelper.newXPath(); NamespaceContext nsContext = xpathHelper.getNamespaceContext(attachTo, reader.getNamespaceContext()); path.setXPathFunctionResolver(new PolicyXPathFunctionResolver(nsContext)); attachTo = PolicyXPathFunction.normalize(attachTo,getSCAPrefix(nsContext)); XPathExpression expression = xpathHelper.compile(path, nsContext, attachTo); attachment.setAttachTo(attachTo); attachment.setAttachToXPathExpression(expression); } catch (XPathExpressionException e) { ContributionReadException ce = new ContributionReadException(e); error(monitor, "ContributionReadException", attachment, ce); } } } private String getSCAPrefix(NamespaceContext nsContext) { Iterator<String> iter = nsContext.getPrefixes(SCA11_NS); while (iter.hasNext()) { String prefix = iter.next(); if (!prefix.equals(XMLConstants.DEFAULT_NS_PREFIX)) { return prefix; } } return "__sca"; } /** * Reads policy sets associated with an external attachment element. * @param subject * @param operation * @param reader */ private void readPolicySets(ExternalAttachment attachment, XMLStreamReader reader) { String value = reader.getAttributeValue(null, POLICY_SETS); if (value != null) { List<PolicySet> policySets = attachment.getPolicySets(); for (StringTokenizer tokens = new StringTokenizer(value); tokens.hasMoreTokens();) { QName qname = getQNameValue(reader, tokens.nextToken()); PolicySet policySet = policyFactory.createPolicySet(); policySet.setName(qname); policySets.add(policySet); } } } public void write(ExternalAttachment attachment, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, XMLStreamException { writePolicySets(attachment, writer, context); writeIntents(attachment, writer, context); writeAttachTo(attachment, writer, context); } private void writeAttachTo(ExternalAttachment attachment, XMLStreamWriter writer, ProcessorContext context) throws XMLStreamException { if ( attachment.getAttachTo() != null ) { writer.writeAttribute(PolicyConstants.ATTACH_TO, attachment.getAttachTo()); } } private void writeIntents(ExternalAttachment attachment, XMLStreamWriter writer, ProcessorContext context) throws XMLStreamException { if (!attachment.getIntents().isEmpty()) { StringBuffer sb = new StringBuffer(); for (Intent intent : attachment.getIntents()) { sb.append(getQualifiedName(intent.getName(), writer)); sb.append(" "); } // Remove the last space sb.deleteCharAt(sb.length() - 1); writer.writeAttribute(PolicyConstants.INTENTS, sb.toString()); } } private void writePolicySets(ExternalAttachment attachment, XMLStreamWriter writer, ProcessorContext context) throws XMLStreamException { if ( !attachment.getPolicySets().isEmpty()) { StringBuffer sb = new StringBuffer(); for (PolicySet ps : attachment.getPolicySets()) { sb.append(getQualifiedName(ps.getName(), writer)); sb.append(" "); } // Remove the last space sb.deleteCharAt(sb.length() - 1); writer.writeAttribute(PolicyConstants.POLICY_SETS, sb.toString()); } } private String getQualifiedName(QName name, XMLStreamWriter writer) throws XMLStreamException { String local = name.getLocalPart(); String prefix = writer.getPrefix(name.getNamespaceURI()); if (prefix != null && prefix.length() > 0) { return prefix + ':' + local; } else { return local; } } /** * Report a error. * * @param problems * @param message * @param model */ private void error(Monitor monitor, String message, Object model, Object... messageParameters) { if (monitor != null) { Problem problem = monitor.createProblem(this.getClass().getName(), Messages.RESOURCE_BUNDLE, Severity.ERROR, model, message, (Object[])messageParameters); monitor.problem(problem); } } }