001: package vqwiki.lex;
002:
003: import org.apache.log4j.Logger;
004:
005: import java.io.File;
006: import java.io.FileOutputStream;
007: import java.io.IOException;
008: import java.io.InputStream;
009: import java.net.URL;
010: import java.net.URLDecoder;
011: import java.util.Properties;
012: import java.security.AccessControlException;
013: import java.io.UnsupportedEncodingException;
014:
015: /**
016: * Manager for lex extensions. Lex extensions are persisted as entries in a file at
017: * WEB-INF/classes/externallex.properties. They are triggered by the special markup:
018: * [<tagname>][</tagname>] where tagname is the name of the external lex
019: * to use process the content between the tags. The entry in this manager maps this name
020: * to an implementation class of {@link ExternalLex} that is used to process the text.
021: *
022: * @author garethc
023: * Date: Jan 6, 2003
024: */
025: public class LexExtender {
026:
027: /**
028: * Logger
029: */
030: private static final Logger logger = Logger
031: .getLogger(LexExtender.class);
032:
033: /**
034: * Properties file to persist in
035: */
036: public static final String LEX_EXTENDER_PROPERTIES_FILE = "/externallex.properties";
037:
038: /**
039: * Singleon instance of the extender
040: */
041: public static LexExtender instance;
042:
043: /**
044: * The pairs of name to class mappings
045: */
046: private Properties properties;
047:
048: /**
049: * Hide constructor - singleton
050: */
051: private LexExtender() {
052: }
053:
054: /**
055: * Get instance of the extender
056: *
057: * @return singleton instance
058: */
059: public static synchronized LexExtender getInstance() {
060: if (instance == null) {
061: instance = new LexExtender();
062: }
063: return instance;
064: }
065:
066: /**
067: * Process the given contents using the lex class that matches with the tag name
068: *
069: * @param tagName tag name == lexer name
070: * @param contents contents to transform
071: * @return transformed contents
072: */
073: public String lexify(String tagName, String contents) {
074: ExternalLex lexer = null;
075: try {
076: lexer = getLexerInstance(tagName);
077: } catch (ClassNotFoundException e) {
078: logger.error("", e);
079: } catch (IllegalAccessException e) {
080: logger.error("", e);
081: } catch (InstantiationException e) {
082: logger.error("", e);
083: }
084: if (lexer == null) {
085: return "???" + tagName + "???";
086: }
087: return lexer.process(contents);
088: }
089:
090: /**
091: * Return the current entries, loading from the persisted file if necessary
092: *
093: * @return entries
094: */
095: private Properties getProperties() {
096: if (properties == null) {
097: InputStream in = LexExtender.class
098: .getResourceAsStream(LEX_EXTENDER_PROPERTIES_FILE);
099: if (in == null) {
100: logger
101: .warn(LEX_EXTENDER_PROPERTIES_FILE
102: + " not found");
103: }
104: properties = new Properties();
105: try {
106: properties.load(in);
107: in.close();
108: } catch (IOException e) {
109: logger.warn(e);
110: }
111: }
112: return properties;
113: }
114:
115: /**
116: * Return an instance of the mapped lexer class for the given name
117: * @param lexName lexer name
118: * @return instance or null if there is no mapping for that name
119: * @throws ClassNotFoundException if the class defined for the name can not be found
120: * @throws IllegalAccessException on security problem
121: * @throws InstantiationException if the lexer can not be instantiated
122: */
123: public ExternalLex getLexerInstance(String lexName)
124: throws ClassNotFoundException, IllegalAccessException,
125: InstantiationException {
126: String className = getProperties().getProperty(lexName);
127: if (className == null) {
128: return null;
129: }
130: Class clazz = Class.forName(className);
131: return (ExternalLex) clazz.newInstance();
132: }
133:
134: /**
135: * Add a new lexer entry and persist the mapping
136: * @param lexName lexer name
137: * @param className class name
138: * @throws IOException if the mapping can not be persisted
139: */
140: public void addLexerEntry(String lexName, String className)
141: throws IOException {
142: getProperties().setProperty(lexName, className);
143: URL base = LexExtender.class
144: .getResource(LEX_EXTENDER_PROPERTIES_FILE);
145: FileOutputStream out = null;
146: File props = null;
147:
148: if (base != null) {
149: String defaultencoding = null;
150: try {
151: defaultencoding = System.getProperty("file.encoding");
152: } catch (AccessControlException ae) {
153: logger
154: .warn("This application server doesn't allow to access "
155: + "file.encoding with System.getProperty. Set default "
156: + "encoding for filename-URL to UTF-8");
157: defaultencoding = "UTF-8";
158: }
159: try {
160: props = new File(URLDecoder.decode(base.getFile(),
161: defaultencoding));
162: } catch (UnsupportedEncodingException e) {
163: logger
164: .error(
165: "The platform's default encoding is not supported in the JDK.",
166: e);
167: try {
168: props = new File(URLDecoder.decode(base.getFile(),
169: "UTF-8"));
170: } catch (UnsupportedEncodingException e1) {
171: logger.fatal(
172: "Even UTF-8 is not supported by this JDK!",
173: e1);
174: }
175: }
176: }
177:
178: try {
179: out = new FileOutputStream(props);
180: getProperties().store(out, "externallex");
181: } finally {
182: if (out != null) {
183: out.close();
184: }
185: }
186: }
187:
188: }
|