diff options
Diffstat (limited to '')
13 files changed, 422 insertions, 265 deletions
diff --git a/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentProcessor.java b/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentProcessor.java index 5db05a2cc7..296677d8b8 100644 --- a/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentProcessor.java +++ b/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/IntentProcessor.java @@ -327,12 +327,13 @@ public class IntentProcessor extends BaseStAXArtifactProcessor implements StAXAr } public void resolve(Intent intent, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { - Monitor monitor = context.getMonitor(); - resolveProfileIntent(intent, resolver, context); - resolveExcludedIntents(intent, resolver, context); - resolveQualifiedIntent(intent, resolver, context); - resolveContrainedTypes(intent, resolver, context); - intent.setUnresolved(false); + if (intent != null && intent.isUnresolved()) { + resolveProfileIntent(intent, resolver, context); + resolveExcludedIntents(intent, resolver, context); + resolveQualifiedIntent(intent, resolver, context); + resolveContrainedTypes(intent, resolver, context); + intent.setUnresolved(false); + } } public QName getArtifactType() { diff --git a/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java b/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java index c1513d9306..6309cc5403 100644 --- a/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java +++ b/sca-java-2.x/trunk/modules/assembly-xml/src/main/java/org/apache/tuscany/sca/policy/xml/PolicySetProcessor.java @@ -66,18 +66,16 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA private PolicyFactory policyFactory; private StAXArtifactProcessor<Object> extensionProcessor; private XPathHelper xpathHelper; + // private XPathFactory xpathFactory; - - public PolicySetProcessor(ExtensionPointRegistry registry, - StAXArtifactProcessor<Object> extensionProcessor) { + public PolicySetProcessor(ExtensionPointRegistry registry, StAXArtifactProcessor<Object> extensionProcessor) { FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class); this.policyFactory = modelFactories.getFactory(PolicyFactory.class); this.extensionProcessor = extensionProcessor; this.xpathHelper = XPathHelper.getInstance(registry); } - /** * Report a exception. * @@ -118,7 +116,8 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA } } - public PolicySet read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, XMLStreamException { + public PolicySet read(XMLStreamReader reader, ProcessorContext context) throws ContributionReadException, + XMLStreamException { PolicySet policySet = null; Monitor monitor = context.getMonitor(); String policySetName = reader.getAttributeValue(null, NAME); @@ -157,7 +156,7 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA //throw ce; } } - + String attachTo = reader.getAttributeValue(null, ATTACH_TO); if (attachTo != null) { try { @@ -211,7 +210,7 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA OMElement policyElement = loadElement(reader); org.apache.neethi.Policy wsPolicy = PolicyEngine.getPolicy(policyElement); policySet.getPolicies().add(wsPolicy); - } */else { + } */else { Object extension = extensionProcessor.read(reader, context); if (extension != null) { PolicyExpression exp = policyFactory.createPolicyExpression(); @@ -220,15 +219,11 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA // check that all the policies in the policy set are // expressed in the same language. Compare against the // first expression we added - if ((policySet.getPolicies().size() > 0) && - (!policySet.getPolicies().get(0).getName().equals(name))){ - error(monitor, - "PolicyLanguageMissmatch", - reader, - policySet.getName(), - policySet.getPolicies().get(0).getName(), - name); - } else { + if ((policySet.getPolicies().size() > 0) && (!policySet.getPolicies().get(0).getName() + .equals(name))) { + error(monitor, "PolicyLanguageMissmatch", reader, policySet.getName(), policySet + .getPolicies().get(0).getName(), name); + } else { policySet.getPolicies().add(exp); } } @@ -260,15 +255,11 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA QName intentName = getQName(reader, INTENT_MAP); intentMap.setProvidedIntent(mappedIntent); - if (!policySet.getIntentMaps().contains(intentMap)){ + if (!policySet.getIntentMaps().contains(intentMap)) { policySet.getIntentMaps().add(intentMap); } else { - Monitor.error(context.getMonitor(), - this, - Messages.RESOURCE_BUNDLE, - "IntentMapIsNotUnique", - policySet.getName().toString(), - mappedIntent.getName().getLocalPart()); + Monitor.error(context.getMonitor(), this, Messages.RESOURCE_BUNDLE, "IntentMapIsNotUnique", policySet + .getName().toString(), mappedIntent.getName().getLocalPart()); } String qualifierName = null; @@ -305,7 +296,8 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA if (qualifierName.equals(providedIntent.getLocalPart())) { readIntentMap(reader, policySet, qualifiedIntent, context); } else { - error(monitor, "IntentMapDoesNotMatch", + error(monitor, + "IntentMapDoesNotMatch", providedIntent, providedIntent, qualifierName, @@ -342,8 +334,8 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA } } - public void write(PolicySet policySet, XMLStreamWriter writer, ProcessorContext context) throws ContributionWriteException, - XMLStreamException { + public void write(PolicySet policySet, XMLStreamWriter writer, ProcessorContext context) + throws ContributionWriteException, XMLStreamException { // Write an <sca:policySet> writer.writeStartElement(SCA11_NS, POLICY_SET); @@ -393,7 +385,8 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA } } - private void resolvePolicies(PolicySet policySet, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { + private void resolvePolicies(PolicySet policySet, ModelResolver resolver, ProcessorContext context) + throws ContributionResolveException { boolean unresolved = false; if (policySet != null) { for (Object o : policySet.getPolicies()) { @@ -476,25 +469,25 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA // intent qualifier. The above code has already checked that the // qualifiers that are there are resolved Intent providedIntent = intentMap.getProvidedIntent(); - if (intentMap.getQualifiers().size() != providedIntent.getQualifiedIntents().size()){ + if (intentMap.getQualifiers().size() != providedIntent.getQualifiedIntents().size()) { String missingQualifiers = ""; - for (Intent loopQualifiedIntent : providedIntent.getQualifiedIntents()){ + for (Intent loopQualifiedIntent : providedIntent.getQualifiedIntents()) { boolean found = false; - for (Qualifier loopQualifier : intentMap.getQualifiers()){ - if (loopQualifier.getIntent().getName().equals(loopQualifiedIntent.getName())){ + for (Qualifier loopQualifier : intentMap.getQualifiers()) { + if (loopQualifier.getIntent().getName().equals(loopQualifiedIntent.getName())) { found = true; break; } } - if (!found){ + if (!found) { missingQualifiers += loopQualifiedIntent.getName().getLocalPart() + " "; } } - if (missingQualifiers.length() > 0){ - Monitor.error(context.getMonitor(), - this, - Messages.RESOURCE_BUNDLE, - "IntentMapMissingQualifiers", + if (missingQualifiers.length() > 0) { + Monitor.error(context.getMonitor(), + this, + Messages.RESOURCE_BUNDLE, + "IntentMapMissingQualifiers", policySet.getName().toString(), providedIntent.getName().getLocalPart(), missingQualifiers); @@ -535,25 +528,27 @@ public class PolicySetProcessor extends BaseStAXArtifactProcessor implements StA policySet.getIntentMaps().addAll(referredPolicySet.getIntentMaps()); } - public void resolve(PolicySet policySet, ModelResolver resolver, ProcessorContext context) throws ContributionResolveException { - Monitor monitor = context.getMonitor(); - resolveProvidedIntents(policySet, resolver, context); - resolveIntentsInMappedPolicies(policySet, resolver, context); - resolveReferredPolicySets(policySet, resolver, context); + public void resolve(PolicySet policySet, ModelResolver resolver, ProcessorContext context) + throws ContributionResolveException { + if (policySet != null && policySet.isUnresolved()) { + resolveProvidedIntents(policySet, resolver, context); + resolveIntentsInMappedPolicies(policySet, resolver, context); + resolveReferredPolicySets(policySet, resolver, context); - for (PolicySet referredPolicySet : policySet.getReferencedPolicySets()) { - includeReferredPolicySets(policySet, referredPolicySet); - } + for (PolicySet referredPolicySet : policySet.getReferencedPolicySets()) { + includeReferredPolicySets(policySet, referredPolicySet); + } - if (policySet.isUnresolved()) { - //resolve the policy attachments - resolvePolicies(policySet, resolver, context); + if (policySet.isUnresolved()) { + //resolve the policy attachments + resolvePolicies(policySet, resolver, context); - /*if ( !policySet.isUnresolved() ) { - resolver.addModel(policySet); - }*/ - } + /*if ( !policySet.isUnresolved() ) { + resolver.addModel(policySet); + }*/ + } - policySet.setUnresolved(false); + policySet.setUnresolved(false); + } } } diff --git a/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java b/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java index 5e32a9a62e..111f1f370c 100644 --- a/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java +++ b/sca-java-2.x/trunk/modules/contribution-osgi/src/main/java/org/apache/tuscany/sca/contribution/osgi/impl/OSGiBundleContributionScanner.java @@ -57,8 +57,6 @@ public class OSGiBundleContributionScanner implements ContributionScanner { return PackageType.BUNDLE; } - - public List<Artifact> scan(Contribution contribution) throws ContributionReadException { Bundle bundle = OSGiBundleActivator.findBundle(contribution.getLocation()); @@ -99,22 +97,28 @@ public class OSGiBundleContributionScanner implements ContributionScanner { //Add artifact to list Artifact artifact = contributionFactory.createArtifact(); artifact.setURI(entryName); - artifact.setLocation(getArtifactURL(contribution, entryName).toString()); + artifact.setLocation(entry.toString()); artifacts.add(artifact); //if Artifact is a JAR, add jar artifacts as well + /* if (entryName.endsWith(".jar") && bundleClassPath.contains(entryName)) { List<String> jarArtifactURIs = getJarArtifacts(entry, entry.openStream()); for( String uri : jarArtifactURIs) { Artifact jarArtifact = contributionFactory.createArtifact(); jarArtifact.setURI(uri); - jarArtifact.setLocation(getArtifactURL(contribution, uri).toString()); - + URL url = bundle.getResource(uri); + String location = null; + if(url!=null) { + location = url.toString(); + } + jarArtifact.setLocation(location); artifacts.add(jarArtifact); } } + */ } } catch (Exception e) { @@ -125,7 +129,7 @@ public class OSGiBundleContributionScanner implements ContributionScanner { contribution.setClassLoader(new BundleClassLoader(bundle)); return artifacts; } - + /** * Retrieve a list of Artifact URIs for a given JAR * @param packageSourceURL @@ -184,27 +188,6 @@ public class OSGiBundleContributionScanner implements ContributionScanner { } - /** - * Given an artifact URI, return it's location URL - * - * @param contribution - * @param artifact - * @return - * @throws ContributionReadException - */ - private URL getArtifactURL(Contribution contribution, String artifact) throws ContributionReadException { - Bundle bundle = null; - try { - bundle = OSGiBundleActivator.findBundle(contribution.getLocation()); - if (bundle != null) { - URL url = bundle.getResource(artifact); - return url; - } - } catch (Exception e) { - } - return null; - } - private static class BundleClassLoader extends ClassLoader { private Bundle bundle; diff --git a/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java b/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java index e4340102fc..f65371ac5f 100644 --- a/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java +++ b/sca-java-2.x/trunk/modules/deployment/src/main/java/org/apache/tuscany/sca/deployment/impl/DeployerImpl.java @@ -301,18 +301,20 @@ public class DeployerImpl implements Deployer { compositeBuilder = compositeBuilders.getCompositeBuilder("org.apache.tuscany.sca.assembly.builder.CompositeBuilder"); - loadSystemContribution(monitorFactory.createMonitor()); + loadSystemContribution(new ProcessorContext(monitorFactory.createMonitor())); inited = true; } - protected void loadSystemContribution(Monitor monitor) { + protected void loadSystemContribution(ProcessorContext context) { DefinitionsFactory definitionsFactory = modelFactories.getFactory(DefinitionsFactory.class); systemDefinitions = definitionsFactory.createDefinitions(); DefinitionsExtensionPoint definitionsExtensionPoint = registry.getExtensionPoint(DefinitionsExtensionPoint.class); + + Monitor monitor = context.getMonitor(); monitor.pushContext("Extension points definitions"); try { for (Definitions defs : definitionsExtensionPoint.getDefinitions()) { @@ -339,6 +341,13 @@ public class DeployerImpl implements Deployer { artifact.setLocation("Derived"); artifact.setModel(systemDefinitions); artifacts.add(artifact); + + // now resolve and add the system contribution + try { + contributionProcessor.resolve(systemContribution, modelResolver, context); + } catch (ContributionResolveException e) { + throw new IllegalStateException(e); + } } protected Contribution cloneSystemContribution(Monitor monitor) { diff --git a/sca-java-2.x/trunk/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java b/sca-java-2.x/trunk/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java index 31a3ae3b9c..56b889b607 100644 --- a/sca-java-2.x/trunk/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java +++ b/sca-java-2.x/trunk/modules/extensibility-equinox/src/main/java/org/apache/tuscany/sca/extensibility/equinox/EquinoxServiceDiscoverer.java @@ -79,6 +79,26 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer { } return scaVersion; } + + /* + private Map<Bundle, Object> bundles = new ConcurrentHashMap<Bundle, Object>(); + + public Object addingBundle(Bundle bundle, BundleEvent event) { + if (isProviderBundle(bundle)) { + bundles.put(bundle, bundle); + System.out.println("Bundle added: " + toString(bundle)); + return bundle; + } + return null; + } + + public void modifiedBundle(Bundle bundle, BundleEvent event, Object object) { + } + + public void removedBundle(Bundle bundle, BundleEvent event, Object object) { + bundles.remove(object); + } + */ public static class ServiceDeclarationImpl implements ServiceDeclaration { private Bundle bundle; @@ -211,6 +231,17 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer { } return true; } + + protected Collection<Bundle> getBundles() { + // return bundles.keySet(); + Set<Bundle> set = new HashSet<Bundle>(); + for (Bundle b : context.getBundles()) { + if (isProviderBundle(b)) { + set.add(b); + } + } + return set; + } public Collection<ServiceDeclaration> getServiceDeclarations(String serviceName) throws IOException { boolean debug = logger.isLoggable(Level.FINE); @@ -222,10 +253,10 @@ public class EquinoxServiceDiscoverer implements ServiceDiscoverer { Set<URL> visited = new HashSet<URL>(); //System.out.println(">>>> getServiceDeclarations()"); - for (Bundle bundle : context.getBundles()) { - if (!isProviderBundle(bundle)) { - continue; - } + for (Bundle bundle : getBundles()) { +// if (!isProviderBundle(bundle)) { +// continue; +// } Enumeration<URL> urls = null; try { // Use getResources to find resources on the classpath of the bundle diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java index d27a8708ee..412e119c76 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/EndpointIntrospector.java @@ -26,7 +26,6 @@ import static org.osgi.framework.Constants.OBJECTCLASS; import static org.osgi.framework.Constants.SERVICE_ID; import java.io.IOException; -import java.net.URL; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -267,6 +266,7 @@ public class EndpointIntrospector { return contribution; } + /* public Contribution loadContribution(Bundle bundle, Composite composite) { try { URL root = bundle.getEntry("/"); @@ -277,6 +277,7 @@ public class EndpointIntrospector { throw new ServiceRuntimeException(e); } } + */ /** * Generate a contribution that contains the composite for the exported service @@ -340,16 +341,16 @@ public class EndpointIntrospector { } // FIXME: Should we scan the owning bundle to create the SCA contribution? - Contribution contribution = loadContribution(bundle, composite); + Contribution contribution = loadContribution(bundle, id, composite); return contribution; } - private Contribution createContribution(Bundle bundle, String id, Composite composite) { + private Contribution loadContribution(Bundle bundle, String id, Composite composite) { Contribution contribution = contributionFactory.createContribution(); contribution.setClassLoader(OSGiHelper.createBundleClassLoader(bundle)); - contribution.setURI("urn:" + id); + contribution.setURI(id); contribution.setLocation(bundle.getEntry("/").toString()); - contribution.getDeployables().add(composite); + deployer.attachDeploymentComposite(contribution, composite, false); ModelResolver modelResolver = new ExtensibleModelResolver(contribution, modelResolvers, factories); contribution.setModelResolver(modelResolver); // compositeProcessor.resolve(composite, modelResolver, new ProcessorContext(registry)); @@ -433,7 +434,7 @@ public class EndpointIntrospector { componentReference.getBindings().addAll(bindings); } - Contribution contribution = loadContribution(bundle, composite); + Contribution contribution = loadContribution(bundle, id, composite); return contribution; } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java index a4b51d9d0c..b0c55fea71 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/OSGiHelper.java @@ -109,8 +109,9 @@ public class OSGiHelper { if (value == null) { return Collections.emptyList(); } - String paths[] = value.trim().split("( |\t|\n|\r|\f|,)+"); - if (paths.length == 0) { + value = value.trim(); + String paths[] = value.split("( |\t|\n|\r|\f|,)+"); + if ("".equals(value) || paths.length == 0) { if (defaultValue != null) { paths = new String[] {defaultValue}; } else { @@ -119,6 +120,10 @@ public class OSGiHelper { } Collection<URL> files = new HashSet<URL>(); for (String path : paths) { + if ("".equals(path)) { + // Skip empty ones + continue; + } if (path.endsWith("/")) { path = path + "*.xml"; } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java index 33faa77c84..97c8b345fa 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/remoteserviceadmin/impl/TopologyManagerImpl.java @@ -23,6 +23,7 @@ import static org.apache.tuscany.sca.implementation.osgi.OSGiProperty.SERVICE_EX import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_EXPORTED_CONFIGS; import static org.osgi.service.remoteserviceadmin.RemoteConstants.SERVICE_IMPORTED; +import java.util.ArrayList; import java.util.Collection; import java.util.Dictionary; import java.util.HashMap; @@ -190,10 +191,11 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList * @see org.osgi.framework.hooks.service.ListenerHook#added(java.util.Collection) */ public void added(Collection listeners) { - synchronized (serviceListeners) { - try { + boolean changed = false; + String[] filters = null; + try { + synchronized (serviceListeners) { Collection<ListenerInfo> listenerInfos = (Collection<ListenerInfo>)listeners; - boolean changed = false; for (ListenerInfo l : listenerInfos) { if (l.getBundleContext().getBundle().getBundleId() == 0L || l.getBundleContext() == context) { // Ignore system and tuscany bundle @@ -217,75 +219,86 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList } } if (changed) { - updateEndpointListenerScope(); - } - } catch (Throwable e) { - logger.log(Level.SEVERE, e.getMessage(), e); - if (e instanceof Error) { - throw (Error)e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException)e; - } else { - // Should not happen - throw new RuntimeException(e); + filters = getFilters(); } } + if (changed) { + updateEndpointListenerScope(filters); + } + } catch (Throwable e) { + logger.log(Level.SEVERE, e.getMessage(), e); + if (e instanceof Error) { + throw (Error)e; + } else if (e instanceof RuntimeException) { + throw (RuntimeException)e; + } else { + // Should not happen + throw new RuntimeException(e); + } } } - private void updateEndpointListenerScope() { - Set<String> filterSet = serviceListeners.keySet(); - + private void updateEndpointListenerScope(String[] filters) { Dictionary<String, Object> props = new Hashtable<String, Object>(); - props.put(ENDPOINT_LISTENER_SCOPE, filterSet.toArray(new String[filterSet.size()])); + props.put(ENDPOINT_LISTENER_SCOPE, filters); endpointListener.setProperties(props); } + private String[] getFilters() { + Set<String> filterSet = serviceListeners.keySet(); + String[] filters = filterSet.toArray(new String[filterSet.size()]); + return filters; + } + private CollectionMap<Class<?>, ListenerInfo> findServiceListeners(EndpointDescription endpointDescription, String matchedFilter) { + Collection<ListenerInfo> listeners = null; synchronized (serviceListeners) { // First find all the listeners that have the matching filter - Collection<ListenerInfo> listeners = serviceListeners.get(matchedFilter); + listeners = serviceListeners.get(matchedFilter); if (listeners == null) { return null; } + listeners = new ArrayList<ListenerInfo>(listeners); + } - // Try to partition the listeners by the interface classes - List<String> interfaceNames = endpointDescription.getInterfaces(); - CollectionMap<Class<?>, ListenerInfo> interfaceToListeners = new CollectionMap<Class<?>, ListenerInfo>(); - for (String i : interfaceNames) { - for (Iterator<ListenerInfo> it = listeners.iterator(); it.hasNext();) { + // Try to partition the listeners by the interface classes + List<String> interfaceNames = endpointDescription.getInterfaces(); + CollectionMap<Class<?>, ListenerInfo> interfaceToListeners = new CollectionMap<Class<?>, ListenerInfo>(); + for (String i : interfaceNames) { + for (Iterator<ListenerInfo> it = listeners.iterator(); it.hasNext();) { + try { + ListenerInfo listener = it.next(); + if (listener.isRemoved()) { + it.remove(); + continue; + } try { - ListenerInfo listener = it.next(); - if (listener.isRemoved()) { - it.remove(); - continue; - } - try { - Class<?> interfaceClass = listener.getBundleContext().getBundle().loadClass(i); - interfaceToListeners.putValue(interfaceClass, listener); - } catch (IllegalStateException e) { - logger.log(Level.WARNING, e.getMessage(), e); - // Ignore the exception - } - } catch (ClassNotFoundException e) { - // Ignore the listener as it cannot load the interface class + // The classloading can be synchronzed against the serviceListeners + Class<?> interfaceClass = listener.getBundleContext().getBundle().loadClass(i); + interfaceToListeners.putValue(interfaceClass, listener); + } catch (IllegalStateException e) { + logger.log(Level.WARNING, e.getMessage(), e); + // Ignore the exception } + } catch (ClassNotFoundException e) { + // Ignore the listener as it cannot load the interface class } } - return interfaceToListeners; } + return interfaceToListeners; } /** * @see org.osgi.framework.hooks.service.ListenerHook#removed(java.util.Collection) */ public void removed(Collection listeners) { - synchronized (serviceListeners) { - try { + boolean changed = false; + String[] filters = null; + try { + synchronized (serviceListeners) { Collection<ListenerInfo> listenerInfos = (Collection<ListenerInfo>)listeners; - boolean changed = false; for (ListenerInfo l : listenerInfos) { if (registration != null && l.getBundleContext() != context) { String key = l.getFilter(); @@ -298,19 +311,22 @@ public class TopologyManagerImpl implements ListenerHook, RemoteServiceAdminList } } if (changed) { - updateEndpointListenerScope(); - } - } catch (Throwable e) { - logger.log(Level.SEVERE, e.getMessage(), e); - if (e instanceof Error) { - throw (Error)e; - } else if (e instanceof RuntimeException) { - throw (RuntimeException)e; - } else { - // Should not happen - throw new RuntimeException(e); + filters = getFilters(); } } + if (changed) { + updateEndpointListenerScope(filters); + } + } catch (Throwable e) { + logger.log(Level.SEVERE, e.getMessage(), e); + if (e instanceof Error) { + throw (Error)e; + } else if (e instanceof RuntimeException) { + throw (RuntimeException)e; + } else { + // Should not happen + throw new RuntimeException(e); + } } } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java index 886e79197d..dbdbbaead8 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/AbstractDiscoveryService.java @@ -19,15 +19,12 @@ package org.apache.tuscany.sca.osgi.service.discovery.impl; -import static org.osgi.service.remoteserviceadmin.EndpointListener.ENDPOINT_LISTENER_SCOPE; - import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Dictionary; -import java.util.HashMap; import java.util.Hashtable; import java.util.Iterator; -import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.logging.Level; @@ -35,9 +32,11 @@ import java.util.logging.Logger; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.LifeCycleListener; +import org.apache.tuscany.sca.core.UtilityExtensionPoint; import org.apache.tuscany.sca.node.NodeFactory; import org.apache.tuscany.sca.node.impl.NodeFactoryImpl; import org.apache.tuscany.sca.osgi.remoteserviceadmin.impl.OSGiHelper; +import org.apache.tuscany.sca.work.WorkScheduler; import org.osgi.framework.Bundle; import org.osgi.framework.BundleContext; import org.osgi.framework.Constants; @@ -60,13 +59,13 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi protected BundleContext context; protected ExtensionPointRegistry registry; + private WorkScheduler workScheduler; - private Map<String, List<EndpointListener>> filtersToListeners = new HashMap<String, List<EndpointListener>>(); - // this is effectively a set which allows for multiple service descriptions with the - // same interface name but different properties and takes care of itself with respect to concurrency - protected Map<EndpointDescription, Bundle> endpointDescriptions = new ConcurrentHashMap<EndpointDescription, Bundle>(); private Map<EndpointListener, Collection<String>> listenersToFilters = - new HashMap<EndpointListener, Collection<String>>(); + new ConcurrentHashMap<EndpointListener, Collection<String>>(); + + protected Map<EndpointDescription, Bundle> endpointDescriptions = + new ConcurrentHashMap<EndpointDescription, Bundle>(); private ServiceTracker trackerTracker; public AbstractDiscoveryService(BundleContext context) { @@ -75,6 +74,10 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi } public void start() { + getExtensionPointRegistry(); + UtilityExtensionPoint utilityExtensionPoint = registry.getExtensionPoint(UtilityExtensionPoint.class); + this.workScheduler = utilityExtensionPoint.getUtility(WorkScheduler.class); + // track the registration of EndpointListener trackerTracker = new ServiceTracker(this.context, EndpointListener.class.getName(), null) { public Object addingService(ServiceReference reference) { @@ -122,66 +125,52 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi return props; } - private synchronized void cacheTracker(ServiceReference reference, Object service) { + private void cacheTracker(ServiceReference reference, Object service) { if (service instanceof EndpointListener) { EndpointListener listener = (EndpointListener)service; - Collection<String> filters = - addTracker(reference, listener, ENDPOINT_LISTENER_SCOPE, filtersToListeners, listenersToFilters); - - triggerCallbacks(null, filters, listener, true); + Collection<String> filters = null; + Collection<EndpointDescription> endpoints = null; + synchronized (this) { + filters = addTracker(reference, listener, EndpointListener.ENDPOINT_LISTENER_SCOPE); + // Take a snapshot of the endpoints + triggerCallbacks(null, filters, listener); + } } } - private synchronized void clearTracker(Object service) { + private void clearTracker(Object service) { if (service instanceof EndpointListener) { - removeTracker((EndpointListener)service, filtersToListeners, listenersToFilters); + synchronized (this) { + removeTracker((EndpointListener)service); + } } } - private synchronized void updateTracker(ServiceReference reference, Object service) { + private void updateTracker(ServiceReference reference, Object service) { if (service instanceof EndpointListener) { EndpointListener listener = (EndpointListener)service; - if (logger.isLoggable(Level.FINE)) { - logger.fine("updating listener: " + listener); + Collection<String> oldFilters = null; + Collection<String> newFilters = null; + Collection<EndpointDescription> endpoints = null; + synchronized (this) { + if (logger.isLoggable(Level.FINE)) { + logger.fine("updating listener: " + listener); + } + oldFilters = removeTracker(listener); + newFilters = addTracker(reference, listener, EndpointListener.ENDPOINT_LISTENER_SCOPE); + triggerCallbacks(oldFilters, newFilters, listener); } - Collection<String> oldFilters = removeTracker(listener, filtersToListeners, listenersToFilters); - - Collection<String> newFilters = - addTracker(reference, listener, ENDPOINT_LISTENER_SCOPE, filtersToListeners, listenersToFilters); - - triggerCallbacks(oldFilters, newFilters, listener, true); } } private void triggerCallbacks(Collection<String> oldInterest, Collection<String> newInterest, - EndpointListener listener, - boolean isFilter) { + EndpointListener listener) { // compute delta between old & new interfaces/filters and // trigger callbacks for any entries in servicesInfo that // match any *additional* interface/filters - Collection<String> deltaInterest = new ArrayList<String>(); - if (newInterest != null && !newInterest.isEmpty()) { - if (oldInterest == null || oldInterest.isEmpty()) { - deltaInterest.addAll(newInterest); - } else { - Iterator<String> i = newInterest.iterator(); - while (i.hasNext()) { - String next = (String)i.next(); - if (!oldInterest.contains(next)) { - deltaInterest.add(next); - } - } - } - } + Collection<String> deltaInterest = getDelta(oldInterest, newInterest); - if (logger.isLoggable(Level.FINE)) { - if (endpointDescriptions.size() > 0) { - logger.fine("search for matches to trigger callbacks with delta: " + deltaInterest); - } else { - logger.fine("nothing to search for matches to trigger callbacks with delta: " + deltaInterest); - } - } Iterator<String> i = deltaInterest.iterator(); while (i.hasNext()) { String next = i.next(); @@ -191,21 +180,74 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi } } - private void triggerCallbacks(EndpointListener listener, String matchedFilter, EndpointDescription sd, int type) { + private Collection<String> getDelta(Collection<String> oldInterest, Collection<String> newInterest) { + if (newInterest == null) { + newInterest = Collections.emptySet(); + } + + Collection<String> deltaInterest = new ArrayList<String>(newInterest); + if (oldInterest == null) { + oldInterest = Collections.emptySet(); + } + deltaInterest.removeAll(oldInterest); + return deltaInterest; + } + + /** + * Notify the endpoint listener + * @param listener + * @param matchedFilter + * @param endpoint + * @param type + */ + private static void notify(EndpointListener listener, String matchedFilter, EndpointDescription endpoint, int type) { switch (type) { case ADDED: - listener.endpointAdded(sd, matchedFilter); + listener.endpointAdded(endpoint, matchedFilter); break; case REMOVED: - listener.endpointRemoved(sd, matchedFilter); + listener.endpointRemoved(endpoint, matchedFilter); break; case MODIFIED: - listener.endpointRemoved(sd, matchedFilter); - listener.endpointAdded(sd, matchedFilter); + listener.endpointRemoved(endpoint, matchedFilter); + listener.endpointAdded(endpoint, matchedFilter); break; } } + private static class Notifier implements Runnable { + private EndpointListener listener; + private String matchedFilter; + private EndpointDescription endpoint; + private int type; + + /** + * @param listener + * @param matchedFilter + * @param endpoint + * @param type + */ + public Notifier(EndpointListener listener, String matchedFilter, EndpointDescription endpoint, int type) { + super(); + this.listener = listener; + this.matchedFilter = matchedFilter; + this.endpoint = endpoint; + this.type = type; + } + + public void run() { + AbstractDiscoveryService.notify(listener, matchedFilter, endpoint, type); + } + } + + private void triggerCallbacks(EndpointListener listener, + String matchedFilter, + EndpointDescription endpoint, + int type) { + workScheduler.scheduleWork(new Notifier(listener, matchedFilter, endpoint, type)); + + } + private boolean filterMatches(String filterValue, EndpointDescription sd) { Filter filter = OSGiHelper.createFilter(context, filterValue); Hashtable<String, Object> props = new Hashtable<String, Object>(sd.getProperties()); @@ -215,63 +257,25 @@ public abstract class AbstractDiscoveryService implements Discovery, LifeCycleLi return filter != null ? filter.match(props) : false; } - static Collection<String> removeTracker(EndpointListener listener, - Map<String, List<EndpointListener>> forwardMap, - Map<EndpointListener, Collection<String>> reverseMap) { - Collection<String> collection = reverseMap.get(listener); - if (collection != null && !collection.isEmpty()) { - reverseMap.remove(listener); - Iterator<String> i = collection.iterator(); - while (i.hasNext()) { - String element = i.next(); - if (forwardMap.containsKey(element)) { - forwardMap.get(element).remove(listener); - } else { - // if the element wasn't on the forwardmap, its a new element and - // shouldn't be returned as part of the collection of old ones - i.remove(); - } - } - } - return collection; + private Collection<String> removeTracker(EndpointListener listener) { + return listenersToFilters.remove(listener); } - @SuppressWarnings("unchecked") - static Collection<String> addTracker(ServiceReference reference, - EndpointListener listener, - String property, - Map<String, List<EndpointListener>> forwardMap, - Map<EndpointListener, Collection<String>> reverseMap) { + private Collection<String> addTracker(ServiceReference reference, EndpointListener listener, String property) { Collection<String> collection = OSGiHelper.getStringCollection(reference, property); - if (logger.isLoggable(Level.FINE)) { - logger.fine("adding listener: " + listener - + " collection: " - + collection - + " registered against prop: " - + property); - } if (collection != null && !collection.isEmpty()) { - reverseMap.put(listener, new ArrayList<String>(collection)); - Iterator<String> i = collection.iterator(); - while (i.hasNext()) { - String element = i.next(); - if (forwardMap.containsKey(element)) { - forwardMap.get(element).add(listener); - } else { - List<EndpointListener> trackerList = new ArrayList<EndpointListener>(); - trackerList.add(listener); - forwardMap.put(element, trackerList); - } - } + listenersToFilters.put(listener, new ArrayList<String>(collection)); } return collection; } - protected synchronized void endpointChanged(EndpointDescription sd, int type) { - for (Map.Entry<EndpointListener, Collection<String>> entry : listenersToFilters.entrySet()) { - for (String filter : entry.getValue()) { - if (filterMatches(filter, sd)) { - triggerCallbacks(entry.getKey(), filter, sd, type); + protected void endpointChanged(EndpointDescription sd, int type) { + synchronized (this) { + for (Map.Entry<EndpointListener, Collection<String>> entry : listenersToFilters.entrySet()) { + for (String filter : entry.getValue()) { + if (filterMatches(filter, sd)) { + triggerCallbacks(entry.getKey(), filter, sd, type); + } } } } diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java index a02be672a2..c9c4cb6a69 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/DomainDiscoveryService.java @@ -49,7 +49,6 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements public void start() { super.start(); - getExtensionPointRegistry(); this.domainRegistryFactory = registry.getExtensionPoint(UtilityExtensionPoint.class).getUtility(DomainRegistryFactory.class); domainRegistryFactory.addListener(this); @@ -80,7 +79,7 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements } } - public synchronized void endpointAdded(Endpoint endpoint) { + public void endpointAdded(Endpoint endpoint) { Implementation impl = endpoint.getComponent().getImplementation(); if (!(impl instanceof OSGiImplementation)) { return; @@ -94,20 +93,24 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements bundleContext = bundle != null ? bundle.getBundleContext() : null; } - // Notify the endpoint listeners - EndpointDescription description = createEndpointDescription(bundleContext, endpoint); - // Set the owning bundle to runtime bundle to avoid NPE + // Notify the endpoint listeners + EndpointDescription description = createEndpointDescription(bundleContext, endpoint); + // Set the owning bundle to runtime bundle to avoid NPE + synchronized (this) { endpointDescriptions.put(description, context.getBundle()); endpointChanged(description, ADDED); + } } - public synchronized void endpointRemoved(Endpoint endpoint) { - EndpointDescription description = createEndpointDescription(context, endpoint); + public void endpointRemoved(Endpoint endpoint) { + EndpointDescription description = createEndpointDescription(context, endpoint); + synchronized (this) { endpointDescriptions.remove(description); endpointChanged(description, REMOVED); + } } - public synchronized void endpointUpdated(Endpoint oldEndpoint, Endpoint newEndpoint) { + public void endpointUpdated(Endpoint oldEndpoint, Endpoint newEndpoint) { // FIXME: This is a quick and dirty way for the update endpointRemoved(oldEndpoint); endpointAdded(newEndpoint); @@ -124,7 +127,7 @@ public class DomainDiscoveryService extends AbstractDiscoveryService implements super.stop(); } } - + @Override protected Dictionary<String, Object> getProperties() { Dictionary<String, Object> props = super.getProperties(); diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java index 56a830a1e6..a31d05acf0 100644 --- a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/java/org/apache/tuscany/sca/osgi/service/discovery/impl/LocalDiscoveryService.java @@ -63,7 +63,6 @@ public class LocalDiscoveryService extends AbstractDiscoveryService implements B public void start() { super.start(); - getExtensionPointRegistry(); UtilityExtensionPoint utilities = this.registry.getExtensionPoint(UtilityExtensionPoint.class); this.deployer = utilities.getUtility(Deployer.class); diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchema b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchema new file mode 100644 index 0000000000..1991eba409 --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/META-INF/services/org.apache.tuscany.sca.contribution.processor.ValidationSchema @@ -0,0 +1,18 @@ +# 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. +# +org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd
diff --git a/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd new file mode 100644 index 0000000000..dc88df965c --- /dev/null +++ b/sca-java-2.x/trunk/modules/node-impl-osgi/src/main/resources/org/osgi/service/remoteserviceadmin/osgi-remoteserviceadmin.xsd @@ -0,0 +1,92 @@ +<!-- + * + * Copyright (c) OSGi Alliance (2008, 2010). All Rights Reserved. + * + * Licensed 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. + * +--> +<schema xmlns="http://www.w3.org/2001/XMLSchema" xmlns:rsa="http://www.osgi.org/xmlns/rsa/v1.0.0" + targetNamespace="http://www.osgi.org/xmlns/rsa/v1.0.0" elementFormDefault="qualified" version="1.0.0"> + <element name="endpoint-descriptions" type="rsa:Tendpoint-descriptions" /> + <complexType name="Tendpoint-descriptions"> + <sequence> + <element name="endpoint-description" type="rsa:Tendpoint-description" minOccurs="1" maxOccurs="unbounded" /> + <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" /> + </sequence> + <anyAttribute /> + </complexType> + <complexType name="Tendpoint-description"> + <sequence> + <element name="property" type="rsa:Tproperty" minOccurs="1" maxOccurs="unbounded" /> + <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" /> + </sequence> + <anyAttribute /> + </complexType> + <complexType name="Tproperty" mixed="true"> + <sequence> + <choice minOccurs="0" maxOccurs="1"> + <element name="array" type="rsa:Tmulti-value" /> + <element name="list" type="rsa:Tmulti-value" /> + <element name="set" type="rsa:Tmulti-value" /> + <element name="xml" type="rsa:Txml" /> + </choice> + <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" /> + </sequence> + <attribute name="name" type="string" use="required" /> + <attribute name="value" type="string" use="optional" /> + <attribute name="value-type" type="rsa:Tvalue-types" default="String" use="optional" /> + <anyAttribute /> + </complexType> + <complexType name="Tmulti-value"> + <sequence> + <element name="value" minOccurs="0" maxOccurs="unbounded" type="rsa:Tvalue" /> + <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" /> + </sequence> + <anyAttribute /> + </complexType> + <complexType name="Tvalue" mixed="true"> + <sequence> + <element name="xml" minOccurs="0" maxOccurs="1" type="rsa:Txml" /> + <any namespace="##other" minOccurs="0" maxOccurs="unbounded" processContents="lax" /> + </sequence> + <anyAttribute /> + </complexType> + <simpleType name="Tvalue-types"> + <restriction base="string"> + <enumeration value="String" /> + <enumeration value="long" /> + <enumeration value="Long" /> + <enumeration value="double" /> + <enumeration value="Double" /> + <enumeration value="float" /> + <enumeration value="Float" /> + <enumeration value="int" /> + <enumeration value="Integer" /> + <enumeration value="byte" /> + <enumeration value="Byte" /> + <enumeration value="char" /> + <enumeration value="Character" /> + <enumeration value="boolean" /> + <enumeration value="Boolean" /> + <enumeration value="short" /> + <enumeration value="Short" /> + </restriction> + </simpleType> + <complexType name="Txml"> + <sequence> + <any namespace="##other" minOccurs="1" maxOccurs="1" processContents="lax" /> + </sequence> + <anyAttribute /> + </complexType> + <attribute name="must-understand" type="boolean" default="false" /> +</schema>
\ No newline at end of file |