Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* 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.myfaces.trinidadinternal.skin;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.StringReader;
import java.text.ParseException;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.ArrayList;
import java.util.Locale;
import java.util.Set;
import java.util.HashSet;
import java.util.HashMap;
import java.util.LinkedList;
import org.apache.myfaces.trinidad.logging.TrinidadLogger;
import org.apache.myfaces.trinidad.share.io.InputStreamProvider;
import org.apache.myfaces.trinidad.share.io.NameResolver;
import org.apache.myfaces.trinidadinternal.agent.TrinidadAgent;
import org.apache.myfaces.trinidadinternal.share.io.CachingInputStreamProvider;
import org.apache.myfaces.trinidadinternal.share.xml.ParseContext;
import org.apache.myfaces.trinidadinternal.share.xml.ParseErrorUtils;
import org.apache.myfaces.trinidadinternal.share.xml.XMLUtils;
import org.apache.myfaces.trinidadinternal.style.util.ModeUtils;
import org.apache.myfaces.trinidadinternal.style.util.NameUtils;
import org.apache.myfaces.trinidadinternal.style.util.StyleUtils;
import org.apache.myfaces.trinidadinternal.style.xml.parse.PropertyNode;
import org.apache.myfaces.trinidadinternal.util.nls.LocaleUtils;
/** As the Skin css file is parsed, methods in this class are called to
* build up a SkinStyleSheetNode.
* TODO figure out if this is thread-safe
*
*/
public class SkinCSSDocumentHandler
{
/* ParseContext is useful for parsing CSS files only because we use it to set/get properties,
* like the current NameResolver and InputStreamProvider.
*/
public SkinCSSDocumentHandler(ParseContext pContext)
{
_parseContext = pContext;
}
/**
* Return the List of SkinStyleSheetNodes that was created
* at the end of parsing the skin css file (endDocument).
*/
public List getSkinStyleSheetNodes()
{
// We now have a list of CompleteSelectorNodes.
// We need to group this list into stylesheet nodes by matching
// the additional information, like direction.
// Then we create a list of SkinStyleSheetNodes.
List skinStyleSheetNodes =
_createSkinStyleSheetNodes(_completeSelectorNodeList, _namespaceMap);
List allSkinStyleSheetNodes = new ArrayList();
if (_imports != null && !_imports.isEmpty())
{
// _imports is a List>();;
for (List nodeList : _imports)
{
for (SkinStyleSheetNode node : nodeList)
{
allSkinStyleSheetNodes.add(node);
}
}
}
allSkinStyleSheetNodes.addAll(skinStyleSheetNodes);
return
allSkinStyleSheetNodes;
}
/**
* Call this at the start of parsing the skin css file.
*/
public void startDocument()
{
// do nothing
}
/**
* Call this at the end of parsing the skin css file.
*/
public void endDocument()
{
// do nothing
}
public void comment(String text)
{
// ignore comments
}
/**
* Call this at the beginning of parsing one set of selectors/properties.
* e.g., .AFDefaultFont, af|breadCrumbs::font
* {font-family:Arial,Helvetica; font-size:small}
*/
public void startSelector()
{
_inStyleRule = true;
// CSS spec says to ignore all @import rules after any other rules are processed.
_ignoreImports = true;
_propertyNodeList = new ArrayList();
}
/**
* Call this at the end of parsing one set of selectors/properties.
* @param selectors A List of Strings, each String is a selector.
* e.g., given the selectors/properties:
* .AFDefaultFont, af|breadCrumbs::font
* {font-family:Arial,Helvetica; font-size:small}
* The selectors in the List are
* ".AFDefaultFont" and "af|breadCrumbs::font"
*/
public void endSelector(List selectors)
{
if (selectors == null)
return;
int selectorNum = selectors.size();
for (int i = 0; i < selectorNum; i++)
{
String selector = selectors.get(i);
CompleteSelectorNode node =
_createCompleteSelectorNode(selector,
_propertyNodeList,
_locales,
_agentAtRuleMatcher,
_selectorPlatforms,
_getSelectorAccProperties(),
_mode);
_completeSelectorNodeList.add(node);
}
// reset flags
_inStyleRule = false;
_propertyNodeList = null;
}
/**
* Call this when a property name/value is found.
* e.g., given the selectors/properties:
* .AFDefaultFont, af|breadCrumbs::font
* {font-family:Arial,Helvetica; font-size:small}
* One property name/value pair is "font-family"/"Arial,Helvetica"
* If the name and value are both non-null and we are in a style rule,
* then a PropertyNode will be created and added to the _propertyNodeList.
* @param name
* @param value
*
*/
public void property(String name, String value)
{
if (_inStyleRule && (_propertyNodeList != null))
{
if (name == null || "".equals(name))
{
_LOG.severe("ERR_PARSING_SKIN_CSS_FILE", new Object[] {name, value});
}
else
_propertyNodeList.add(new PropertyNode(name, value));
}
}
/**
* Call when you have an atRule. This will do further processing.
* @param atRule The @rule string
* e.g., @namespace af url(http:\\www.xxx.com);
* e.g., @agent gecko { .foo {color:red}}
*/
public void atRule(String atRule)
{
// parse the atRule further here.
boolean importRule = atRule.startsWith(_AT_IMPORT);
boolean charsetRule = atRule.startsWith(_AT_CHARSET);
if (atRule != null)
{
if (importRule)
{
if (_ignoreImports)
{
// according to the css spec, @imports must come before all other rules (except @charset).
if (_LOG.isWarning())
_LOG.warning("AT_IMPORT_NOT_FIRST", atRule);
}
else
_parseImport(atRule);
}
else if (atRule.startsWith(_AT_NAMESPACE))
{
_parseNamespace(_namespaceMap, atRule);
}
else if (atRule.startsWith(_AT_AGENT))
{
_parseCustomAtRule(_AT_AGENT, atRule);
}
else if (atRule.startsWith(_AT_PLATFORM))
{
_parseCustomAtRule(_AT_PLATFORM, atRule);
}
else if (atRule.startsWith(_AT_LOCALE))
{
_parseCustomAtRule(_AT_LOCALE, atRule);
}
else if (atRule.startsWith(_AT_ACC_PROFILE))
{
_parseCustomAtRule(_AT_ACC_PROFILE, atRule);
}
else if (atRule.startsWith(_AT_MODE))
{
_parseCustomAtRule(_AT_MODE, atRule);
}
// for now, ignore other atRules in a skinning css file
// CSS spec says you ignore all @import rules after any other rules are processed
// (except for @charset).
if(!importRule && !charsetRule)
{
_ignoreImports = true;
}
}
}
private void _parseNamespace(Map namespaceMap, String atRule)
{
// TODO deal with default namespaces that don't have prefixes??
String[] namespaceParts = atRule.split("\\s+");
if (namespaceParts.length > 2)
{
String url = _extractUrl(namespaceParts[2]);
namespaceMap.put(namespaceParts[1], url);
}
}
private String _extractUrl(String urlString)
{
urlString = urlString.trim();
// first, strip off the url( and );
if (urlString.startsWith("url("))
urlString = urlString.substring(4);
if (urlString.endsWith(");"))
urlString = urlString.substring(0, urlString.length() - 2);
else if (urlString.endsWith(";"))
urlString = urlString.substring(0, urlString.length() - 1);
// second, strip off the starting/ending quotes if there are any
urlString = SkinStyleSheetParserUtils.trimQuotes(urlString);
return urlString;
}
private void _parseImport(String type)
{
// parse any of these
//@import "mystyle.css";
//@import url("mystyle.css");
//@import url(mystyle.css);
// strip out @import any spaces, then get the url
String styleSheetName = _extractUrl(type.substring(8));
try
{
if (_imports == null)
_imports = new ArrayList>();
_imports.add(_parseImportStyleSheetFile(_parseContext, styleSheetName, List.class));
}
catch (IOException e)
{
if (_LOG.isSevere())
_LOG.severe("CANNOT_LOAD_STYLESHEET", styleSheetName);
_LOG.severe(e);
}
catch (ParseException e)
{
_LOG.severe(e);
}
}
private List _parseImportStyleSheetFile(
ParseContext context,
String sourceName,
Class> expectedType)
throws IOException, ParseException
{
// Step 1. Find the name resolver
NameResolver resolver = XMLUtils.getResolver(context);
if (resolver == null)
{
if (_LOG.isWarning())
_LOG.warning("Internal error: couldn't find NameResolver");
return Collections.emptyList();
}
// Step 2. Find an InputStreamProvider. Mark a dependency on the base provider (if necessary)
InputStreamProvider importProvider = resolver.getProvider(sourceName);
InputStreamProvider baseProvider = XMLUtils.getInputStreamProvider(context);
if (baseProvider instanceof CachingInputStreamProvider)
{
// important: hasSourceChanged takes into account this dependency
((CachingInputStreamProvider)baseProvider).addCacheDependency(importProvider);
}
// Step 3. Detect if this will be a circular include
ArrayList