Search in sources :

Example 1 with Mixins

use of org.apache.tapestry5.annotations.Mixins in project tapestry-5 by apache.

the class SaxTemplateParser method possibleTapestryComponent.

/**
 * @param elementName
 * @param identifiedType
 *         the type of the element, usually null, but may be the
 *         component type derived from element
 */
private void possibleTapestryComponent(TemplateParserState state, String elementName, String identifiedType) {
    String id = null;
    String type = identifiedType;
    String mixins = null;
    int count = tokenStream.getAttributeCount();
    Location location = getLocation();
    List<TemplateToken> attributeTokens = CollectionFactory.newList();
    for (int i = 0; i < count; i++) {
        QName qname = tokenStream.getAttributeName(i);
        if (isXMLSpaceAttribute(qname))
            continue;
        // The name will be blank for an xmlns: attribute
        String localName = qname.getLocalPart();
        if (InternalUtils.isBlank(localName))
            continue;
        String uri = qname.getNamespaceURI();
        String value = tokenStream.getAttributeValue(i);
        Version version = NAMESPACE_URI_TO_VERSION.get(uri);
        if (version != null) {
            if (T_5_4.sameOrEarlier(version)) {
                strictMixinParameters = true;
            }
            if (localName.equalsIgnoreCase(ID_ATTRIBUTE_NAME)) {
                id = nullForBlank(value);
                validateId(id, "Component id '%s' is not valid; component ids must be valid Java identifiers: start with a letter, and consist of letters, numbers and underscores.");
                continue;
            }
            if (type == null && localName.equalsIgnoreCase(TYPE_ATTRIBUTE_NAME)) {
                type = nullForBlank(value);
                continue;
            }
            if (localName.equalsIgnoreCase(MIXINS_ATTRIBUTE_NAME)) {
                mixins = nullForBlank(value);
                continue;
            }
        // Anything else is the name of a Tapestry component parameter
        // that is simply
        // not part of the template's doctype for the element being
        // instrumented.
        }
        attributeTokens.add(new AttributeToken(uri, localName, value, location));
    }
    boolean isComponent = (id != null || type != null);
    if (mixins != null && !isComponent)
        throw new TapestryException(String.format("You may not specify mixins for element <%s> because it does not represent a component (which requires either an id attribute or a type attribute).", elementName), location, null);
    if (isComponent) {
        tokenAccumulator.add(new StartComponentToken(elementName, id, type, mixins, location));
    } else {
        tokenAccumulator.add(new StartElementToken(tokenStream.getNamespaceURI(), elementName, location));
    }
    addDefineNamespaceTokens();
    tokenAccumulator.addAll(attributeTokens);
    if (id != null)
        componentIds.put(id, location);
    processBody(state.insideComponent(isComponent));
}
Also used : Version(org.apache.tapestry5.internal.services.SaxTemplateParser.Version) QName(javax.xml.namespace.QName) TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException) Location(org.apache.tapestry5.commons.Location)

Example 2 with Mixins

use of org.apache.tapestry5.annotations.Mixins in project tapestry-5 by apache.

the class TapestryAppInitializer method announceStartup.

/**
 * Announce application startup, by logging (at INFO level) the names of all pages,
 * components, mixins and services.
 */
public void announceStartup() {
    if (// if info logging is off we can stop now
    !logger.isInfoEnabled()) {
        return;
    }
    long toFinish = System.currentTimeMillis();
    SymbolSource source = registry.getService("SymbolSource", SymbolSource.class);
    StringBuilder buffer = new StringBuilder("Startup status:\n\nServices:\n\n");
    Formatter f = new Formatter(buffer);
    int unrealized = 0;
    ServiceActivityScoreboard scoreboard = registry.getService(ServiceActivityScoreboard.class);
    List<ServiceActivity> serviceActivity = scoreboard.getServiceActivity();
    int longest = 0;
    for (ServiceActivity activity : serviceActivity) {
        Status status = activity.getStatus();
        longest = Math.max(longest, activity.getServiceId().length());
        if (status == Status.DEFINED || status == Status.VIRTUAL)
            unrealized++;
    }
    String formatString = "%" + longest + "s: %s\n";
    for (ServiceActivity activity : serviceActivity) {
        f.format(formatString, activity.getServiceId(), activity.getStatus().name());
    }
    f.format("\n%4.2f%% unrealized services (%d/%d)\n", 100. * unrealized / serviceActivity.size(), unrealized, serviceActivity.size());
    f.format("\nApplication '%s' (version %s) startup time: %,d ms to build IoC Registry, %,d ms overall.", appName, source.valueForSymbol(TapestryHttpSymbolConstants.APPLICATION_VERSION), registryCreatedTime - startTime, toFinish - startTime);
    String version = source.valueForSymbol(TapestryHttpSymbolConstants.TAPESTRY_VERSION);
    boolean productionMode = Boolean.parseBoolean(source.valueForSymbol(TapestryHttpSymbolConstants.PRODUCTION_MODE));
    buffer.append("\n\n");
    buffer.append(" ______                  __             ____\n");
    buffer.append("/_  __/__ ____  ___ ___ / /_______ __  / __/\n");
    buffer.append(" / / / _ `/ _ \\/ -_|_-</ __/ __/ // / /__ \\ \n");
    buffer.append("/_/  \\_,_/ .__/\\__/___/\\__/_/  \\_, / /____/\n");
    f.format("        /_/                   /___/  %s%s\n\n", version, productionMode ? "" : " (development mode)");
    // log multi-line string with OS-specific line endings (TAP5-2294)
    logger.info(buffer.toString().replaceAll("\\n", System.getProperty("line.separator")));
}
Also used : Status(org.apache.tapestry5.ioc.services.Status) SymbolSource(org.apache.tapestry5.ioc.services.SymbolSource) Formatter(java.util.Formatter) ServiceActivityScoreboard(org.apache.tapestry5.ioc.services.ServiceActivityScoreboard) ServiceActivity(org.apache.tapestry5.ioc.services.ServiceActivity)

Example 3 with Mixins

use of org.apache.tapestry5.annotations.Mixins in project tapestry-5 by apache.

the class ParameterWorker method createComputedParameterConduit.

@SuppressWarnings("all")
private ComputedValue<FieldConduit<Object>> createComputedParameterConduit(final String parameterName, final String fieldTypeName, final Parameter annotation, final MethodHandle defaultMethodHandle) {
    boolean primitive = PlasticUtils.isPrimitive(fieldTypeName);
    final boolean allowNull = annotation.allowNull() && !primitive;
    return new ComputedValue<FieldConduit<Object>>() {

        public ParameterConduit get(InstanceContext context) {
            final InternalComponentResources icr = context.get(InternalComponentResources.class);
            final Class fieldType = classCache.forName(fieldTypeName);
            final PerThreadValue<ParameterState> stateValue = perThreadManager.createValue();
            return new ParameterConduit() {

                // Default value for parameter, computed *once* at
                // page load time.
                private Object defaultValue = classCache.defaultValueForType(fieldTypeName);

                private Binding parameterBinding;

                boolean loaded = false;

                private boolean invariant = false;

                {
                    // Inform the ComponentResources about the parameter conduit, so it can be
                    // shared with mixins.
                    icr.setParameterConduit(parameterName, this);
                    icr.getPageLifecycleCallbackHub().addPageLoadedCallback(new Runnable() {

                        public void run() {
                            load();
                        }
                    });
                }

                private ParameterState getState() {
                    ParameterState state = stateValue.get();
                    if (state == null) {
                        state = new ParameterState();
                        state.value = defaultValue;
                        stateValue.set(state);
                    }
                    return state;
                }

                private boolean isLoaded() {
                    return loaded;
                }

                public void set(Object instance, InstanceContext context, Object newValue) {
                    ParameterState state = getState();
                    if (!loaded) {
                        state.value = newValue;
                        defaultValue = newValue;
                        return;
                    }
                    // This will catch read-only or unbound parameters.
                    writeToBinding(newValue);
                    state.value = newValue;
                    // If caching is enabled for the parameter (the typical case) and the
                    // component is currently rendering, then the result
                    // can be cached in this ParameterConduit (until the component finishes
                    // rendering).
                    state.cached = annotation.cache() && icr.isRendering();
                }

                private Object readFromBinding() {
                    Object result;
                    try {
                        Object boundValue = parameterBinding.get();
                        result = typeCoercer.coerce(boundValue, fieldType);
                    } catch (RuntimeException ex) {
                        throw new TapestryException(String.format("Failure reading parameter '%s' of component %s: %s", parameterName, icr.getCompleteId(), ExceptionUtils.toMessage(ex)), parameterBinding, ex);
                    }
                    if (result == null && !allowNull) {
                        throw new TapestryException(String.format("Parameter '%s' of component %s is bound to null. This parameter is not allowed to be null.", parameterName, icr.getCompleteId()), parameterBinding, null);
                    }
                    return result;
                }

                private void writeToBinding(Object newValue) {
                    if (parameterBinding == null) {
                        return;
                    }
                    try {
                        Object coerced = typeCoercer.coerce(newValue, parameterBinding.getBindingType());
                        parameterBinding.set(coerced);
                    } catch (RuntimeException ex) {
                        throw new TapestryException(String.format("Failure writing parameter '%s' of component %s: %s", parameterName, icr.getCompleteId(), ExceptionUtils.toMessage(ex)), icr, ex);
                    }
                }

                public void reset() {
                    if (!invariant) {
                        getState().reset(defaultValue);
                    }
                }

                public void load() {
                    if (logger.isDebugEnabled()) {
                        logger.debug("{} loading parameter {}", icr.getCompleteId(), parameterName);
                    }
                    if (!icr.isBound(parameterName)) {
                        if (logger.isDebugEnabled()) {
                            logger.debug("{} parameter {} not yet bound", icr.getCompleteId(), parameterName);
                        }
                        // Otherwise, construct a default binding, or use one provided from
                        // the component.
                        Binding binding = getDefaultBindingForParameter();
                        if (logger.isDebugEnabled()) {
                            logger.debug("{} parameter {} bound to default {}", icr.getCompleteId(), parameterName, binding);
                        }
                        if (binding != null) {
                            icr.bindParameter(parameterName, binding);
                        }
                    }
                    parameterBinding = icr.getBinding(parameterName);
                    loaded = true;
                    invariant = parameterBinding != null && parameterBinding.isInvariant();
                    getState().value = defaultValue;
                }

                public boolean isBound() {
                    return parameterBinding != null;
                }

                public Object get(Object instance, InstanceContext context) {
                    if (!isLoaded()) {
                        return defaultValue;
                    }
                    ParameterState state = getState();
                    if (state.cached || !isBound()) {
                        return state.value;
                    }
                    // Read the parameter's binding and cast it to the
                    // field's type.
                    Object result = readFromBinding();
                    if (invariant || (annotation.cache() && icr.isRendering())) {
                        state.value = result;
                        state.cached = true;
                    }
                    return result;
                }

                private Binding getDefaultBindingForParameter() {
                    if (InternalUtils.isNonBlank(annotation.value())) {
                        return bindingSource.newBinding("default " + parameterName, icr, annotation.defaultPrefix(), annotation.value());
                    }
                    if (annotation.autoconnect()) {
                        return defaultProvider.defaultBinding(parameterName, icr);
                    }
                    // Invoke the default method and install any value or Binding returned there.
                    invokeDefaultMethod();
                    return parameterBinding;
                }

                private void invokeDefaultMethod() {
                    if (defaultMethodHandle == null) {
                        return;
                    }
                    if (logger.isDebugEnabled()) {
                        logger.debug("{} invoking method {} to obtain default for parameter {}", icr.getCompleteId(), defaultMethodHandle, parameterName);
                    }
                    MethodInvocationResult result = defaultMethodHandle.invoke(icr.getComponent());
                    result.rethrow();
                    Object defaultValue = result.getReturnValue();
                    if (defaultValue == null) {
                        return;
                    }
                    if (defaultValue instanceof Binding) {
                        parameterBinding = (Binding) defaultValue;
                        return;
                    }
                    parameterBinding = new LiteralBinding(null, "default " + parameterName, defaultValue);
                }
            };
        }
    };
}
Also used : LiteralBinding(org.apache.tapestry5.internal.bindings.LiteralBinding) Binding(org.apache.tapestry5.Binding) LiteralBinding(org.apache.tapestry5.internal.bindings.LiteralBinding) InternalComponentResources(org.apache.tapestry5.internal.InternalComponentResources) TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException)

Example 4 with Mixins

use of org.apache.tapestry5.annotations.Mixins in project tapestry-5 by apache.

the class ComponentAssemblerImpl method createEmbeddedAssembler.

public EmbeddedComponentAssembler createEmbeddedAssembler(String embeddedId, String componentClassName, EmbeddedComponentModel embeddedModel, String mixins, Location location) {
    try {
        if (InternalUtils.isBlank(componentClassName)) {
            throw new TapestryException("You must specify the type via t:type, the element, or @Component annotation.", location, null);
        }
        EmbeddedComponentAssemblerImpl embedded = new EmbeddedComponentAssemblerImpl(assemblerSource, instantiatorSource, componentClassResolver, componentClassName, getSelector(), embeddedModel, mixins, location, strictMixinParameters);
        if (embeddedIdToAssembler == null)
            embeddedIdToAssembler = CollectionFactory.newMap();
        embeddedIdToAssembler.put(embeddedId, embedded);
        if (embeddedModel != null) {
            for (String publishedParameterName : embeddedModel.getPublishedParameters()) {
                if (publishedParameterToEmbeddedId == null)
                    publishedParameterToEmbeddedId = CollectionFactory.newCaseInsensitiveMap();
                String existingEmbeddedId = publishedParameterToEmbeddedId.get(publishedParameterName);
                if (existingEmbeddedId != null) {
                    throw new TapestryException(String.format("Parameter '%s' of embedded component '%s' can not be published as a parameter of component %s, as it has previously been published by embedded component '%s'.", publishedParameterName, embeddedId, instantiator.getModel().getComponentClassName(), existingEmbeddedId), location, null);
                }
                publishedParameterToEmbeddedId.put(publishedParameterName, embeddedId);
            }
        }
        return embedded;
    } catch (Exception ex) {
        throw new TapestryException(String.format("Failure creating embedded component '%s' of %s: %s", embeddedId, instantiator.getModel().getComponentClassName(), ExceptionUtils.toMessage(ex)), location, ex);
    }
}
Also used : TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException) TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException)

Example 5 with Mixins

use of org.apache.tapestry5.annotations.Mixins in project tapestry-5 by apache.

the class EmbeddedComponentAssemblerImpl method addMixin.

private void addMixin(String className, String... order) {
    Instantiator mixinInstantiator = instantiatorSource.getInstantiator(className);
    String mixinId = InternalUtils.lastTerm(className);
    if (mixinIdToInstantiator.containsKey(mixinId))
        throw new TapestryException(String.format("Mixins applied to a component must be unique. Mixin '%s' has already been applied.", mixinId), location, null);
    mixinIdToInstantiator.put(mixinId, mixinInstantiator);
    mixinsIdToOrderConstraints.put(mixinId, order);
}
Also used : Instantiator(org.apache.tapestry5.internal.services.Instantiator) TapestryException(org.apache.tapestry5.commons.internal.util.TapestryException)

Aggregations

TapestryException (org.apache.tapestry5.commons.internal.util.TapestryException)7 InternalComponentResources (org.apache.tapestry5.internal.InternalComponentResources)2 Instantiator (org.apache.tapestry5.internal.services.Instantiator)2 Formatter (java.util.Formatter)1 QName (javax.xml.namespace.QName)1 Binding (org.apache.tapestry5.Binding)1 MixinClasses (org.apache.tapestry5.annotations.MixinClasses)1 Mixins (org.apache.tapestry5.annotations.Mixins)1 OnEvent (org.apache.tapestry5.annotations.OnEvent)1 Location (org.apache.tapestry5.commons.Location)1 LiteralBinding (org.apache.tapestry5.internal.bindings.LiteralBinding)1 Version (org.apache.tapestry5.internal.services.SaxTemplateParser.Version)1 ServiceActivity (org.apache.tapestry5.ioc.services.ServiceActivity)1 ServiceActivityScoreboard (org.apache.tapestry5.ioc.services.ServiceActivityScoreboard)1 Status (org.apache.tapestry5.ioc.services.Status)1 SymbolSource (org.apache.tapestry5.ioc.services.SymbolSource)1 JSONObject (org.apache.tapestry5.json.JSONObject)1 ComponentLibraryInfo (org.apache.tapestry5.services.ComponentLibraryInfo)1 LibraryMapping (org.apache.tapestry5.services.LibraryMapping)1 TextStreamResponse (org.apache.tapestry5.util.TextStreamResponse)1