001// Copyright 2006-2013 The Apache Software Foundation 002// 003// Licensed under the Apache License, Version 2.0 (the "License"); 004// you may not use this file except in compliance with the License. 005// You may obtain a copy of the License at 006// 007// http://www.apache.org/licenses/LICENSE-2.0 008// 009// Unless required by applicable law or agreed to in writing, software 010// distributed under the License is distributed on an "AS IS" BASIS, 011// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 012// See the License for the specific language governing permissions and 013// limitations under the License. 014 015package org.apache.tapestry5.internal.services; 016 017import org.apache.tapestry5.SymbolConstants; 018import org.apache.tapestry5.ioc.Messages; 019import org.apache.tapestry5.ioc.Resource; 020import org.apache.tapestry5.ioc.annotations.PostInjection; 021import org.apache.tapestry5.ioc.annotations.Symbol; 022import org.apache.tapestry5.ioc.internal.util.URLChangeTracker; 023import org.apache.tapestry5.ioc.services.ClasspathURLConverter; 024import org.apache.tapestry5.model.ComponentModel; 025import org.apache.tapestry5.services.InvalidationEventHub; 026import org.apache.tapestry5.services.UpdateListener; 027import org.apache.tapestry5.services.messages.ComponentMessagesSource; 028import org.apache.tapestry5.services.messages.PropertiesFileParser; 029import org.apache.tapestry5.services.pageload.ComponentResourceLocator; 030import org.apache.tapestry5.services.pageload.ComponentResourceSelector; 031 032import java.util.Arrays; 033import java.util.List; 034import java.util.Locale; 035 036public class ComponentMessagesSourceImpl implements ComponentMessagesSource, UpdateListener 037{ 038 private final MessagesSourceImpl messagesSource; 039 040 private final MessagesBundle appCatalogBundle; 041 042 private class ComponentModelBundle implements MessagesBundle 043 { 044 private final ComponentModel model; 045 046 public ComponentModelBundle(ComponentModel model) 047 { 048 this.model = model; 049 } 050 051 public Resource getBaseResource() 052 { 053 return model.getBaseResource(); 054 } 055 056 public Object getId() 057 { 058 return model.getComponentClassName(); 059 } 060 061 public MessagesBundle getParent() 062 { 063 ComponentModel parentModel = model.getParentModel(); 064 065 if (parentModel == null) 066 return appCatalogBundle; 067 068 return new ComponentModelBundle(parentModel); 069 } 070 } 071 072 public ComponentMessagesSourceImpl(@Symbol(SymbolConstants.PRODUCTION_MODE) 073 boolean productionMode, List<Resource> appCatalogResources, PropertiesFileParser parser, 074 ComponentResourceLocator resourceLocator, ClasspathURLConverter classpathURLConverter) 075 { 076 this(productionMode, appCatalogResources, resourceLocator, parser, new URLChangeTracker(classpathURLConverter)); 077 } 078 079 ComponentMessagesSourceImpl(boolean productionMode, Resource appCatalogResource, 080 ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker) 081 { 082 this(productionMode, Arrays.asList(appCatalogResource), resourceLocator, parser, tracker); 083 } 084 085 ComponentMessagesSourceImpl(boolean productionMode, List<Resource> appCatalogResources, 086 ComponentResourceLocator resourceLocator, PropertiesFileParser parser, URLChangeTracker tracker) 087 { 088 messagesSource = new MessagesSourceImpl(productionMode, productionMode ? null : tracker, resourceLocator, 089 parser); 090 091 appCatalogBundle = createAppCatalogBundle(appCatalogResources); 092 } 093 094 @PostInjection 095 public void setupReload(ReloadHelper reloadHelper) 096 { 097 reloadHelper.addReloadCallback(new Runnable() 098 { 099 public void run() 100 { 101 messagesSource.invalidate(); 102 } 103 }); 104 } 105 106 public void checkForUpdates() 107 { 108 messagesSource.checkForUpdates(); 109 } 110 111 public Messages getMessages(ComponentModel componentModel, Locale locale) 112 { 113 return getMessages(componentModel, new ComponentResourceSelector(locale)); 114 } 115 116 public Messages getMessages(ComponentModel componentModel, ComponentResourceSelector selector) 117 { 118 MessagesBundle bundle = new ComponentModelBundle(componentModel); 119 120 return messagesSource.getMessages(bundle, selector); 121 } 122 123 public Messages getApplicationCatalog(Locale locale) 124 { 125 return messagesSource.getMessages(appCatalogBundle, new ComponentResourceSelector(locale)); 126 } 127 128 private MessagesBundle createAppCatalogBundle(List<Resource> resources) 129 { 130 MessagesBundle current = null; 131 132 for (Resource r : resources) 133 { 134 current = createMessagesBundle(r, current); 135 } 136 137 return current; 138 } 139 140 private MessagesBundle createMessagesBundle(final Resource resource, final MessagesBundle parent) 141 { 142 return new MessagesBundle() 143 { 144 public Resource getBaseResource() 145 { 146 return resource; 147 } 148 149 public Object getId() 150 { 151 return resource.getPath(); 152 } 153 154 public MessagesBundle getParent() 155 { 156 return parent; 157 } 158 }; 159 } 160 161 public InvalidationEventHub getInvalidationEventHub() 162 { 163 return messagesSource; 164 } 165}