public final void notify(final String upstreamDependency, String downstreamDependency) { if (downstreamDependency == null) { notifyForGenericListener(upstreamDependency); return; } // Handle if the downstream dependency is "class level", meaning we need to figure out the // specific downstream MID this metadata provider wants to update/refresh. if (MetadataIdentificationUtils.isIdentifyingClass(downstreamDependency)) { // We have not identified an instance-specific downstream MID, so we'll need to calculate an // instance-specific downstream MID to retrieve. downstreamDependency = resolveDownstreamDependencyIdentifier(upstreamDependency); // We skip if the resolution method returns null, as it doesn't want to continue for some // reason if (downstreamDependency == null) { return; } Assert.isTrue( MetadataIdentificationUtils.isIdentifyingInstance(downstreamDependency), "An instance-specific downstream MID was required by '" + getClass().getName() + "' (not '" + downstreamDependency + "')"); // We only need to proceed if the downstream dependency relationship is not already // registered. // It is unusual to register a direct downstream relationship given it costs dependency // registration memory and class-level notifications will always occur anyway. if (metadataDependencyRegistry .getDownstream(upstreamDependency) .contains(downstreamDependency)) { return; } } // We should now have an instance-specific "downstream dependency" that can be processed by this // class Assert.isTrue( MetadataIdentificationUtils.getMetadataClass(downstreamDependency) .equals(MetadataIdentificationUtils.getMetadataClass(getProvidesType())), "Unexpected downstream notification for '" + downstreamDependency + "' to this provider (which uses '" + getProvidesType() + "'"); // We no longer notify downstreams here, as the "get" operation with eviction will ensure the // main get(String) method below will be fired and it // directly notified downstreams as part of that method (BPA 10 Dec 2010) metadataService.get(downstreamDependency, true); }
public final String getIdForPhysicalJavaType(final String physicalJavaTypeIdentifier) { Assert.isTrue( MetadataIdentificationUtils.getMetadataClass(physicalJavaTypeIdentifier) .equals( MetadataIdentificationUtils.getMetadataClass( PhysicalTypeIdentifier.getMetadataIdentiferType())), "Expected a valid physical Java type instance identifier (not '" + physicalJavaTypeIdentifier + "')"); JavaType javaType = PhysicalTypeIdentifier.getJavaType(physicalJavaTypeIdentifier); ContextualPath path = PhysicalTypeIdentifier.getPath(physicalJavaTypeIdentifier); return createLocalIdentifier(javaType, path); }
/** * Assists creating a local metadata identification string (MID) from any presented {@link * MemberHoldingTypeDetails} implementation. This is achieved by extracting the {@link * IdentifiableJavaStructure#getDeclaredByMetadataId()} and converting it into a {@link JavaType} * and {@link Path}, then calling {@link #createLocalIdentifier(JavaType, Path)}. * * @param memberHoldingTypeDetails the member holder from which the declaring type information * should be extracted (required) * @return a MID produced by {@link #createLocalIdentifier(JavaType, Path)} for the extracted Java * type in the extract Path (never null) */ protected String getLocalMid(final MemberHoldingTypeDetails memberHoldingTypeDetails) { JavaType governorType = memberHoldingTypeDetails.getName(); // Extract out the metadata provider class (we need this later to extract just the Path it is // located in) String providesType = MetadataIdentificationUtils.getMetadataClass( memberHoldingTypeDetails.getDeclaredByMetadataId()); ContextualPath path = PhysicalTypeIdentifierNamingUtils.getPath( providesType, memberHoldingTypeDetails.getDeclaredByMetadataId()); // Produce the local MID we're going to use to make the request return createLocalIdentifier(governorType, path); }
public void notifyDownstream(final String upstreamDependency) { try { metadataLogger.startEvent(); if (metadataService != null) { // First dispatch the fine-grained, instance-specific // dependencies. Set<String> notifiedDownstreams = new HashSet<String>(); for (final String downstream : getDownstream(upstreamDependency)) { if (metadataLogger.getTraceLevel() > 0) { metadataLogger.log(upstreamDependency + " -> " + downstream); } // No need to ensure upstreamDependency is different from // downstream, as that's taken care of in the // isValidDependency() method try { final String responsibleClass = MetadataIdentificationUtils.getMetadataClass(downstream); metadataLogger.startTimer(responsibleClass); metadataService.notify(upstreamDependency, downstream); } finally { metadataLogger.stopTimer(); } notifiedDownstreams.add(downstream); } // Next dispatch the coarse-grained, class-specific // dependencies. // We only do it if the upstream is not class specific, as // otherwise we'd have handled class-specific dispatch in // previous loop if (!MetadataIdentificationUtils.isIdentifyingClass(upstreamDependency)) { final String asClass = MetadataIdentificationUtils.getMetadataClassId(upstreamDependency); for (final String downstream : getDownstream(asClass)) { // We don't notify a downstream if it had a direct // instance-specific dependency and was already notified // in previous loop // We also don't notify if upstream is the same as // downstream, as it doesn't make sense to notify // yourself of an event // (such a condition is only possible if an instance // registered to receive class-specific notifications // and that instance // caused an event to fire) if (!notifiedDownstreams.contains(downstream) && !upstreamDependency.equals(downstream)) { if (metadataLogger.getTraceLevel() > 0) { metadataLogger.log(upstreamDependency + " -> " + downstream + " [via class]"); } try { final String responsibleClass = MetadataIdentificationUtils.getMetadataClass(downstream); metadataLogger.startTimer(responsibleClass); metadataService.notify(upstreamDependency, downstream); } finally { metadataLogger.stopTimer(); } } } } notifiedDownstreams = null; } // Finally dispatch the general-purpose additional listeners for (final MetadataNotificationListener listener : listeners) { if (metadataLogger.getTraceLevel() > 1) { metadataLogger.log( upstreamDependency + " -> " + upstreamDependency + " [" + listener.getClass().getSimpleName() + "]"); } try { final String responsibleClass = listener.getClass().getName(); metadataLogger.startTimer(responsibleClass); listener.notify(upstreamDependency, null); } finally { metadataLogger.stopTimer(); } } } finally { metadataLogger.stopEvent(); } }
public void notify(String upstreamDependency, String downstreamDependency) { ProjectMetadata projectMetadata = projectOperations.getProjectMetadata(); if (projectMetadata == null) { return; } if (MetadataIdentificationUtils.isIdentifyingClass(downstreamDependency)) { Assert.isTrue( MetadataIdentificationUtils.getMetadataClass(upstreamDependency) .equals( MetadataIdentificationUtils.getMetadataClass( PhysicalTypeIdentifier.getMetadataIdentiferType())), "Expected class-level notifications only for PhysicalTypeIdentifier (not '" + upstreamDependency + "')"); ClassOrInterfaceTypeDetails cid = typeLocationService.getTypeForIdentifier(upstreamDependency); boolean processed = false; if (MemberFindingUtils.getAnnotationOfType(cid.getAnnotations(), RooJavaType.ROO_GWT_REQUEST) != null) { ClassOrInterfaceTypeDetails proxy = gwtTypeService.lookupProxyFromRequest(cid); if (proxy != null) { JavaType typeName = PhysicalTypeIdentifier.getJavaType(proxy.getDeclaredByMetadataId()); Path typePath = PhysicalTypeIdentifier.getPath(proxy.getDeclaredByMetadataId()); downstreamDependency = GwtLocatorMetadata.createIdentifier(typeName, typePath); processed = true; } } if (!processed && MemberFindingUtils.getAnnotationOfType(cid.getAnnotations(), RooJavaType.ROO_GWT_PROXY) == null) { boolean found = false; for (ClassOrInterfaceTypeDetails classOrInterfaceTypeDetails : typeLocationService.findClassesOrInterfaceDetailsWithAnnotation( RooJavaType.ROO_GWT_PROXY)) { AnnotationMetadata annotationMetadata = GwtUtils.getFirstAnnotation( classOrInterfaceTypeDetails, GwtUtils.ROO_PROXY_REQUEST_ANNOTATIONS); if (annotationMetadata != null) { AnnotationAttributeValue<?> attributeValue = annotationMetadata.getAttribute("value"); if (attributeValue != null) { String mirrorName = GwtUtils.getStringValue(attributeValue); if (mirrorName != null && cid.getName().getFullyQualifiedTypeName().equals(attributeValue.getValue())) { found = true; JavaType typeName = PhysicalTypeIdentifier.getJavaType( classOrInterfaceTypeDetails.getDeclaredByMetadataId()); Path typePath = PhysicalTypeIdentifier.getPath( classOrInterfaceTypeDetails.getDeclaredByMetadataId()); downstreamDependency = GwtLocatorMetadata.createIdentifier(typeName, typePath); break; } } } } if (!found) { return; } } else if (!processed) { // A physical Java type has changed, and determine what the corresponding local metadata // identification string would have been JavaType typeName = PhysicalTypeIdentifier.getJavaType(upstreamDependency); Path typePath = PhysicalTypeIdentifier.getPath(upstreamDependency); downstreamDependency = GwtLocatorMetadata.createIdentifier(typeName, typePath); } // We only need to proceed if the downstream dependency relationship is not already registered // (if it's already registered, the event will be delivered directly later on) if (metadataDependencyRegistry .getDownstream(upstreamDependency) .contains(downstreamDependency)) { return; } } // We should now have an instance-specific "downstream dependency" that can be processed by this // class Assert.isTrue( MetadataIdentificationUtils.getMetadataClass(downstreamDependency) .equals(MetadataIdentificationUtils.getMetadataClass(getProvidesType())), "Unexpected downstream notification for '" + downstreamDependency + "' to this provider (which uses '" + getProvidesType() + "'"); metadataService.get(downstreamDependency, true); }
private boolean isNotificationForJavaType(final String mid) { return MetadataIdentificationUtils.getMetadataClass(mid) .equals( MetadataIdentificationUtils.getMetadataClass( PhysicalTypeIdentifier.getMetadataIdentiferType())); }
public final MetadataItem get(final String metadataIdentificationString) { Assert.isTrue( MetadataIdentificationUtils.getMetadataClass(metadataIdentificationString) .equals(MetadataIdentificationUtils.getMetadataClass(getProvidesType())), "Unexpected request for '" + metadataIdentificationString + "' to this provider (which uses '" + getProvidesType() + "'"); // Remove the upstream dependencies for this instance (we'll be recreating them later, if // needed) metadataDependencyRegistry.deregisterDependencies(metadataIdentificationString); // Compute the identifier for the Physical Type Metadata we're correlated with String governorPhysicalTypeIdentifier = getGovernorPhysicalTypeIdentifier(metadataIdentificationString); // Obtain the physical type PhysicalTypeMetadata governorPhysicalTypeMetadata = (PhysicalTypeMetadata) metadataService.get(governorPhysicalTypeIdentifier); if (governorPhysicalTypeMetadata == null || !governorPhysicalTypeMetadata.isValid()) { // We can't get even basic information about the physical type, so abort (the ITD will be // deleted by ItdFileDeletionService) return null; } // Flag to indicate whether we'll even try to create this metadata boolean produceMetadata = false; // Determine if we should generate the metadata on the basis of it containing a trigger // annotation ClassOrInterfaceTypeDetails cid = null; if (governorPhysicalTypeMetadata.getMemberHoldingTypeDetails() instanceof ClassOrInterfaceTypeDetails) { cid = (ClassOrInterfaceTypeDetails) governorPhysicalTypeMetadata.getMemberHoldingTypeDetails(); // Only create metadata if the type is annotated with one of the metadata triggers for (JavaType trigger : metadataTriggers) { if (cid.getAnnotation(trigger) != null) { produceMetadata = true; break; } } } // Fall back to ignoring trigger annotations if (ignoreTriggerAnnotations) { produceMetadata = true; } // Cancel production if the governor type details are required, but aren't available if (dependsOnGovernorTypeDetailAvailability && cid == null) { produceMetadata = false; } // Cancel production if the governor is not a class, and the subclass only wants to know about // classes if (cid != null && dependsOnGovernorBeingAClass && cid.getPhysicalTypeCategory() != PhysicalTypeCategory.CLASS) { produceMetadata = false; } String itdFilename = governorPhysicalTypeMetadata.getItdCanonicalPath(this); if (!produceMetadata && isGovernor(cid) && fileManager.exists(itdFilename)) { // We don't seem to want metadata anymore, yet the ITD physically exists, so get rid of it // This might be because the trigger annotation has been removed, the governor is missing a // class declaration, etc. deleteItd( metadataIdentificationString, itdFilename, "not required for governor " + cid.getName(), true); return null; } if (produceMetadata) { // This type contains an annotation we were configured to detect, or there is an ITD (which // may need deletion), so we need to produce the metadata JavaType aspectName = governorPhysicalTypeMetadata.getItdJavaType(this); ItdTypeDetailsProvidingMetadataItem metadata = getMetadata( metadataIdentificationString, aspectName, governorPhysicalTypeMetadata, itdFilename); // There is no requirement to register a direct connection with the physical type and this // metadata because changes will // trickle down via the class-level notification registered by convention by // AbstractItdMetadataProvider subclasses (BPA 10 Dec 2010) if (metadata == null || !metadata.isValid()) { // The metadata couldn't be created properly deleteItd(metadataIdentificationString, itdFilename, "", false); return null; } // By this point we have a valid MetadataItem, but it might not contain any members for the // resulting ITD etc // Handle the management of the ITD file boolean deleteItdFile = false; ItdTypeDetails itdTypeDetails = metadata.getMemberHoldingTypeDetails(); if (itdTypeDetails == null) { // The ITD has no members deleteItdFile = true; } if (!deleteItdFile) { // We have some members in the ITD, so decide if we're to write something to disk ItdSourceFileComposer itdSourceFileComposer = new ItdSourceFileComposer(metadata.getMemberHoldingTypeDetails()); // Decide whether the get an ITD on-disk based on whether there is physical content to write if (itdSourceFileComposer.isContent()) { // We have content to write itdDiscoveryService.addItdTypeDetails(itdTypeDetails); String itd = itdSourceFileComposer.getOutput(); fileManager.createOrUpdateTextFileIfRequired(itdFilename, itd, false); } else { // We don't have content to write deleteItdFile = true; } } if (deleteItdFile) { deleteItd(metadataIdentificationString, itdFilename, null, false); } // Eagerly notify that the metadata has been updated; this also registers the metadata hash // code in the superclass' cache to avoid // unnecessary subsequent notifications if it hasn't changed notifyIfRequired(metadata); return metadata; } return null; }