| /* |
| 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. |
| */ |
| package org.apache.wiki.ui; |
| |
| import org.apache.commons.lang3.StringUtils; |
| import org.apache.log4j.Logger; |
| import org.apache.wiki.InternalWikiException; |
| import org.apache.wiki.WikiContext; |
| import org.apache.wiki.api.core.Engine; |
| import org.apache.wiki.modules.BaseModuleManager; |
| import org.apache.wiki.modules.WikiModuleInfo; |
| import org.apache.wiki.preferences.Preferences; |
| import org.apache.wiki.preferences.Preferences.TimeFormat; |
| |
| import javax.servlet.ServletContext; |
| import javax.servlet.http.HttpServletRequest; |
| import javax.servlet.jsp.PageContext; |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.text.SimpleDateFormat; |
| import java.util.ArrayList; |
| import java.util.Collection; |
| import java.util.Collections; |
| import java.util.Date; |
| import java.util.Enumeration; |
| import java.util.LinkedHashMap; |
| import java.util.Map; |
| import java.util.Properties; |
| import java.util.Set; |
| import java.util.TimeZone; |
| import java.util.TreeSet; |
| |
| |
| /** |
| * This class takes care of managing JSPWiki templates. This class also provides the ResourceRequest mechanism. |
| * |
| * @since 2.1.62 |
| */ |
| public class DefaultTemplateManager extends BaseModuleManager implements TemplateManager { |
| |
| private static final Logger log = Logger.getLogger( DefaultTemplateManager.class ); |
| |
| /** |
| * Creates a new TemplateManager. There is typically one manager per engine. |
| * |
| * @param engine The owning engine. |
| * @param properties The property list used to initialize this. |
| */ |
| public DefaultTemplateManager( final Engine engine, final Properties properties ) { |
| super( engine ); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| // FIXME: Does not work yet |
| public boolean templateExists( final String templateName ) { |
| final ServletContext context = m_engine.getServletContext(); |
| try( final InputStream in = context.getResourceAsStream( getPath( templateName ) + "ViewTemplate.jsp" ) ) { |
| if( in != null ) { |
| return true; |
| } |
| } catch( final IOException e ) { |
| log.error( e.getMessage(), e ); |
| } |
| return false; |
| } |
| |
| /** |
| * Tries to locate a given resource from the template directory. If the given resource is not found under the current name, returns the |
| * path to the corresponding one in the default template. |
| * |
| * @param sContext The servlet context |
| * @param name The name of the resource |
| * @return The name of the resource which was found. |
| */ |
| private static String findResource( final ServletContext sContext, final String name ) { |
| String resourceName = name; |
| try( final InputStream is = sContext.getResourceAsStream( resourceName ) ) { |
| if( is == null ) { |
| final String defname = makeFullJSPName( DEFAULT_TEMPLATE, removeTemplatePart( resourceName ) ); |
| try( final InputStream iis = sContext.getResourceAsStream( defname ) ) { |
| resourceName = iis != null ? defname : null; |
| } |
| } |
| } catch( final IOException e ) { |
| log.error( "unable to open " + name + " as resource stream", e ); |
| } |
| return resourceName; |
| } |
| |
| /** |
| * Attempts to find a resource from the given template, and if it's not found |
| * attempts to locate it from the default template. |
| * @param sContext servlet context used to search for the resource |
| * @param template template used to search for the resource |
| * @param name resource name |
| * @return the Resource for the given template and name. |
| */ |
| private static String findResource( final ServletContext sContext, final String template, final String name ) { |
| if( name.charAt(0) == '/' ) { |
| // This is already a full path |
| return findResource( sContext, name ); |
| } |
| final String fullname = makeFullJSPName( template, name ); |
| return findResource( sContext, fullname ); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public String findJSP( final PageContext pageContext, final String name ) { |
| final ServletContext sContext = pageContext.getServletContext(); |
| return findResource( sContext, name ); |
| } |
| |
| /** |
| * Removes the template part of a name. |
| */ |
| private static String removeTemplatePart( String name ) { |
| int idx = 0; |
| if( name.startsWith( "/" ) ) { |
| idx = 1; |
| } |
| |
| idx = name.indexOf('/', idx); |
| if( idx != -1 ) { |
| idx = name.indexOf('/', idx+1); // Find second "/" |
| if( idx != -1 ) { |
| name = name.substring( idx+1 ); |
| } |
| } |
| |
| if( log.isDebugEnabled() ) { |
| log.debug( "Final name = "+name ); |
| } |
| return name; |
| } |
| |
| /** |
| * Returns the full name (/templates/foo/bar) for name=bar, template=foo. |
| * |
| * @param template The name of the template. |
| * @param name The name of the resource. |
| * @return The full name for a template. |
| */ |
| private static String makeFullJSPName( final String template, final String name ) { |
| return "/" + DIRECTORY + "/" + template + "/" + name; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public String findJSP( final PageContext pageContext, final String template, final String name ) { |
| if( name == null || template == null ) { |
| log.fatal("findJSP() was asked to find a null template or name (" + template + "," + name + ")." + " JSP page '" + |
| ( ( HttpServletRequest )pageContext.getRequest() ).getRequestURI() + "'" ); |
| throw new InternalWikiException( "Illegal arguments to findJSP(); please check logs." ); |
| } |
| |
| return findResource( pageContext.getServletContext(), template, name ); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public String findResource( final WikiContext ctx, final String template, final String name ) { |
| if( m_engine.getServletContext() != null ) { |
| return findResource( m_engine.getServletContext(), template, name ); |
| } |
| |
| return getPath(template)+"/"+name; |
| } |
| |
| /* |
| * Returns a property, as defined in the template. The evaluation is lazy, i.e. the properties are not loaded until the template is |
| * actually used for the first time. |
| */ |
| /* |
| public String getTemplateProperty( WikiContext context, String key ) |
| { |
| String template = context.getTemplate(); |
| |
| try |
| { |
| Properties props = (Properties)m_propertyCache.getFromCache( template, -1 ); |
| |
| if( props == null ) |
| { |
| try |
| { |
| props = getTemplateProperties( template ); |
| |
| m_propertyCache.putInCache( template, props ); |
| } |
| catch( IOException e ) |
| { |
| log.warn("IO Exception while reading template properties",e); |
| |
| return null; |
| } |
| } |
| |
| return props.getProperty( key ); |
| } |
| catch( NeedsRefreshException ex ) |
| { |
| // FIXME |
| return null; |
| } |
| } |
| */ |
| /** |
| * Returns an absolute path to a given template. |
| */ |
| private static String getPath( final String template ) { |
| return "/" + DIRECTORY + "/" + template + "/"; |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public Set< String > listSkins( final PageContext pageContext, final String template ) { |
| final String place = makeFullJSPName( template, SKIN_DIRECTORY ); |
| final ServletContext sContext = pageContext.getServletContext(); |
| final Set< String > skinSet = sContext.getResourcePaths( place ); |
| final Set< String > resultSet = new TreeSet<>(); |
| |
| if( log.isDebugEnabled() ) { |
| log.debug( "Listings skins from " + place ); |
| } |
| |
| if( skinSet != null ) { |
| final String[] skins = skinSet.toArray( new String[]{} ); |
| for( final String skin : skins ) { |
| final String[] s = StringUtils.split( skin, "/" ); |
| if( s.length > 2 && skin.endsWith( "/" ) ) { |
| final String skinName = s[ s.length - 1 ]; |
| resultSet.add( skinName ); |
| if( log.isDebugEnabled() ) { |
| log.debug( "...adding skin '" + skinName + "'" ); |
| } |
| } |
| } |
| } |
| |
| return resultSet; |
| } |
| |
| |
| /** {@inheritDoc} */ |
| @Override |
| public Map< String, String > listTimeFormats( final PageContext pageContext ) { |
| final WikiContext context = WikiContext.findContext( pageContext ); |
| final Properties props = m_engine.getWikiProperties(); |
| final ArrayList< String > tfArr = new ArrayList<>(40); |
| final LinkedHashMap< String, String > resultMap = new LinkedHashMap<>(); |
| |
| /* filter timeformat properties */ |
| for( final Enumeration< ? > e = props.propertyNames(); e.hasMoreElements(); ) { |
| final String name = ( String )e.nextElement(); |
| if( name.startsWith( TIMEFORMATPROPERTIES ) ) { |
| tfArr.add( name ); |
| } |
| } |
| |
| /* fetch actual formats */ |
| if( tfArr.size() == 0 ) {/* no props found - make sure some default formats are avail */ |
| tfArr.add( "dd-MMM-yy" ); |
| tfArr.add( "d-MMM-yyyy" ); |
| tfArr.add( "EEE, dd-MMM-yyyy, zzzz" ); |
| } else { |
| Collections.sort( tfArr ); |
| |
| for (int i = 0; i < tfArr.size(); i++) { |
| tfArr.set(i, props.getProperty(tfArr.get(i))); |
| } |
| } |
| |
| final String prefTimeZone = Preferences.getPreference( context, "TimeZone" ); |
| final TimeZone tz = TimeZone.getTimeZone( prefTimeZone ); |
| |
| final Date d = new Date(); // current date |
| try { |
| // dummy format pattern |
| final SimpleDateFormat fmt = Preferences.getDateFormat( context, TimeFormat.DATETIME ); |
| fmt.setTimeZone( tz ); |
| |
| for( final String s : tfArr ) { |
| try { |
| final String f = s; |
| fmt.applyPattern( f ); |
| resultMap.put( f, fmt.format( d ) ); |
| } catch( final IllegalArgumentException e ) { |
| } // skip parameter |
| } |
| } catch( final IllegalArgumentException e ) {} // skip parameter |
| |
| return resultMap; |
| } |
| |
| /* |
| * Always returns a valid property map. |
| */ |
| /* |
| private Properties getTemplateProperties( String templateName ) |
| throws IOException |
| { |
| Properties p = new Properties(); |
| |
| ServletContext context = m_engine.getServletContext(); |
| |
| InputStream propertyStream = context.getResourceAsStream(getPath(templateName)+PROPERTYFILE); |
| |
| if( propertyStream != null ) |
| { |
| p.load( propertyStream ); |
| |
| propertyStream.close(); |
| } |
| else |
| { |
| log.debug("Template '"+templateName+"' does not have a propertyfile '"+PROPERTYFILE+"'."); |
| } |
| |
| return p; |
| } |
| */ |
| |
| /** {@inheritDoc} */ |
| @Override |
| public Collection< WikiModuleInfo > modules() { |
| return new ArrayList<>(); |
| } |
| |
| /** {@inheritDoc} */ |
| @Override |
| public WikiModuleInfo getModuleInfo( final String moduleName ) { |
| return null; |
| } |
| |
| } |