| Method from org.apache.tiles.definition.UrlDefinitionsFactory Detail: |
protected void addDefinitions(Definitions definitions,
TilesRequestContext tilesContext) throws DefinitionsFactoryException {
Locale locale = localeResolver.resolveLocale(tilesContext);
if (isContextProcessed(tilesContext)) {
return;
}
if (locale == null) {
return;
}
processedLocales.add(locale);
List< String > postfixes = calculatePostfixes(locale);
Map< String, Definition > localeDefsMap = new HashMap< String, Definition >();
for (Object postfix : postfixes) {
// For each postfix, all the sources must be loaded.
for (Object source : sources) {
URL url = (URL) source;
String path = url.toExternalForm();
String newPath = concatPostfix(path, (String) postfix);
try {
URL newUrl = new URL(newPath);
URLConnection connection = newUrl.openConnection();
connection.connect();
lastModifiedDates.put(newUrl.toExternalForm(),
connection.getLastModified());
// Definition must be collected, starting from the base
// source up to the last localized file.
Map< String, Definition > defsMap = reader
.read(connection.getInputStream());
if (defsMap != null) {
localeDefsMap.putAll(defsMap);
}
} catch (FileNotFoundException e) {
// File not found. continue.
if (LOG.isDebugEnabled()) {
LOG.debug("File " + newPath + " not found, continue");
}
} catch (IOException e) {
throw new DefinitionsFactoryException(
"I/O error processing configuration.");
}
}
}
// At the end of definitions loading, they can be assigned to
// Definitions implementation, to allow inheritance resolution.
definitions.addDefinitions(localeDefsMap, localeResolver
.resolveLocale(tilesContext));
}
Appends locale-specific Definition objects to an existing
Definitions set by reading locale-specific versions of
the applied sources. |
public void addSource(Object source) throws DefinitionsFactoryException {
if (source == null) {
throw new DefinitionsFactoryException(
"Source object must not be null");
}
if (!(source instanceof URL)) {
throw new DefinitionsFactoryException(
"Source object must be an URL");
}
sources.add(source);
}
Adds a source where Definition objects are stored.
Implementations should publish what type of source object they expect.
The source should contain enough information to resolve a configuration
source containing definitions. The source should be a "base" source for
configurations. Internationalization and Localization properties will be
applied by implementations to discriminate the correct data sources based
on locale. |
protected static List calculatePostfixes(Locale locale) {
final List< String > result = new ArrayList< String >();
final String language = locale.getLanguage();
final int languageLength = language.length();
final String country = locale.getCountry();
final int countryLength = country.length();
final String variant = locale.getVariant();
final int variantLength = variant.length();
// The default configuration file must be loaded to allow correct
// definition inheritance.
result.add("");
if (languageLength + countryLength + variantLength == 0) {
//The locale is "", "", "".
return result;
}
final StringBuffer temp = new StringBuffer();
temp.append('_");
temp.append(language);
if (languageLength > 0) {
result.add(temp.toString());
}
if (countryLength + variantLength == 0) {
return result;
}
temp.append('_");
temp.append(country);
if (countryLength > 0) {
result.add(temp.toString());
}
if (variantLength == 0) {
return result;
} else {
temp.append('_");
temp.append(variant);
result.add(temp.toString());
return result;
}
}
Calculate the postfixes along the search path from the base bundle to the
bundle specified by baseName and locale.
Method copied from java.util.ResourceBundle |
protected String concatPostfix(String name,
String postfix) {
if (postfix == null) {
return name;
}
// Search file name extension.
// take care of Unix files starting with .
int dotIndex = name.lastIndexOf(".");
int lastNameStart = name.lastIndexOf(java.io.File.pathSeparator);
if (dotIndex < 1 || dotIndex < lastNameStart) {
return name + postfix;
}
String ext = name.substring(dotIndex);
name = name.substring(0, dotIndex);
return name + postfix + ext;
}
Concat postfix to the name. Take care of existing filename extension.
Transform the given name "name.ext" to have "name" + "postfix" + "ext".
If there is no ext, return "name" + "postfix". |
protected Definitions createDefinitions() {
return new DefinitionsImpl();
}
Creates a new instance of Definitions. Override this method
to provide your custom instance of Definitions. |
public Definition getDefinition(String name,
TilesRequestContext tilesContext) throws DefinitionsFactoryException {
Definitions definitions = getDefinitions();
Locale locale = null;
if (tilesContext != null) {
locale = localeResolver.resolveLocale(tilesContext);
if (!isContextProcessed(tilesContext)) {
synchronized (definitions) {
addDefinitions(definitions, tilesContext);
}
}
}
return definitions.getDefinition(name, locale);
}
Returns a Definition object that matches the given name and
Tiles context. |
protected Definitions getDefinitions() throws DefinitionsFactoryException {
return definitions;
}
Returns the definitions holder object. |
public void init(Map params) throws TilesException {
String readerClassName =
params.get(DefinitionsFactory.READER_IMPL_PROPERTY);
if (readerClassName != null) {
reader = (DefinitionsReader) ClassUtil.instantiate(readerClassName);
} else {
reader = new DigesterDefinitionsReader();
}
reader.init(params);
String resolverClassName = params
.get(DefinitionsFactory.LOCALE_RESOLVER_IMPL_PROPERTY);
if (resolverClassName != null) {
localeResolver = (LocaleResolver) ClassUtil.instantiate(resolverClassName);
} else {
localeResolver = new DefaultLocaleResolver();
}
localeResolver.init(params);
definitions = readDefinitions();
}
Initializes the DefinitionsFactory and its subcomponents.
Implementations may support configuration properties to be passed in via
the params Map. |
protected boolean isContextProcessed(TilesRequestContext tilesContext) {
return processedLocales.contains(localeResolver
.resolveLocale(tilesContext));
}
Indicates whether a given context has been processed or not.
This method can be used to avoid unnecessary synchronization of the
DefinitionsFactory in multi-threaded situations. Check the return of
isContextProcessed before synchronizing the object and reading
locale-specific definitions. |
public Definitions readDefinitions() throws DefinitionsFactoryException {
Definitions definitions = createDefinitions();
try {
for (Object source1 : sources) {
URL source = (URL) source1;
URLConnection connection = source.openConnection();
connection.connect();
lastModifiedDates.put(source.toExternalForm(),
connection.getLastModified());
Map< String, Definition > defsMap = reader
.read(connection.getInputStream());
definitions.addDefinitions(defsMap);
}
} catch (IOException e) {
throw new DefinitionsFactoryException("I/O error accessing source.", e);
}
return definitions;
}
Creates and returns a Definitions set by reading
configuration data from the applied sources. |
public void refresh() throws DefinitionsFactoryException {
LOG.debug("Updating Tiles definitions. . .");
synchronized (definitions) {
Definitions newDefs = readDefinitions();
definitions.reset();
definitions.addDefinitions(newDefs.getBaseDefinitions());
}
}
|
public boolean refreshRequired() {
boolean status = false;
Set< String > urls = lastModifiedDates.keySet();
try {
for (String urlPath : urls) {
Long lastModifiedDate = lastModifiedDates.get(urlPath);
URL url = new URL(urlPath);
URLConnection connection = url.openConnection();
connection.connect();
long newModDate = connection.getLastModified();
if (newModDate != lastModifiedDate) {
status = true;
break;
}
}
} catch (Exception e) {
LOG.warn("Exception while monitoring update times.", e);
return true;
}
return status;
}
Indicates whether the DefinitionsFactory is out of date and needs to be
reloaded. |