001: /*
002: * Created on Mar 17, 2004
003: *
004: * To change the template for this generated file go to
005: * Window>Preferences>Java>Code Generation>Code and Comments
006: */
007: package org.xdev.base.core.compiler;
008:
009: import java.io.File;
010: import java.util.ArrayList;
011: import java.util.Iterator;
012: import java.util.List;
013: import java.util.HashMap;
014:
015: import org.xdev.base.core.BASE;
016: import org.xdev.base.core.IPage;
017: import org.xdev.base.core.compiler.instruction.AbstractInstruction;
018: import org.xdev.base.core.compiler.lexer.AbstractLexer;
019: import org.xdev.base.core.compiler.type.AbstractType;
020: import org.xdev.base.core.compiler.validator.AbstractValidator;
021: import org.xdev.base.core.manager.PluginManager;
022: import org.xdev.base.core.object.Configuration;
023: import org.xdev.base.log.LoggerWriter;
024: import org.xdev.base.resource.IDataSource;
025: import org.xdev.base.xssl.XContainer;
026: import org.xdev.base.xssl.XSSLAction;
027: import org.xdev.base.xssl.XSSLComponent;
028: import org.xdev.base.xssl.XSSLReturn;
029: import org.xdev.base.xssl.manage.ITransactionFinalizable;
030: import org.xdev.base.core.vm.config.AbstractConfig;
031: import org.xdev.base.core.vm.filter.AbstractCompilerFilter;
032:
033: import org.apache.log4j.Level;
034: import org.jaxen.jdom.JDOMXPath;
035: import org.jdom.Attribute;
036: import org.jdom.CDATA;
037: import org.jdom.Comment;
038: import org.jdom.Document;
039: import org.jdom.Element;
040: import org.jdom.Text;
041: import org.jdom.Namespace;
042: import org.jdom.input.SAXBuilder;
043: import org.jdom.transform.JDOMSource;
044:
045: import java.io.StringReader;
046: import java.io.StringWriter;
047:
048: import javax.xml.transform.Transformer;
049: import javax.xml.transform.TransformerFactory;
050: import javax.xml.transform.stream.StreamResult;
051: import javax.xml.transform.stream.StreamSource;
052:
053: /**
054: * @author AYegorov
055: *
056: * To change the template for this generated type comment go to
057: * Window>Preferences>Java>Code Generation>Code and Comments
058: */
059: public abstract class AXCompiler {
060: public static final String PATH = "path";
061: public static final String PROPERTY_IMPORT = "property-import";
062: public static final String ID = "id";
063: public static final String PROPERTY = "property";
064: public static final String PROPERTIES = "properties";
065: public static final String CONTAINER = "#CONTAINER";
066: public static final String TEXT = "TEXT";
067: public static final String COMMENT = "COMMENT";
068: public static final String CLASS_TYPES = "class-types";
069: public static final String TYPE_DESCRIPTOR = "type-descriptor"; //$NON-NLS-1$
070: public static final String GLOBAL_IDENTIFIER = "base";
071: public static final String INTERNAL_COMMAND = "xssl";
072: public static final String NAMESPACE_DECL = "xmlns:";
073: public static final String BASE_CLASS = "baseClass";
074: public static final String VALUE = "value";
075: public static final String APPLICATION = "application";
076: public static final String LOG_TO_CONSOLE = "log-to-console";
077: public static final String URI = "uri";
078: public static final String PLUGIN_LOCATION = "plugin-location";
079: public static final String PLUGIN_DEFINITION = "plugin-definition";
080: public static final String TRUE = "true";
081: public static final String FILE_PATH = "$file-path";
082: public static final String PLUGIN_XPATH = "//plugin";
083: public static final String TYPE = "type";
084: public static final String IMPORT = "import";
085: public static final String CONFIGURATION = "configuration";
086: public static final String STRICT_COMPILATION = "strict-compilation";
087: public static final String DISABLED = "disabled";
088: public static final String OVERWRITE_ID = "overwrite-id";
089: public static final String SET_TAG_NAME = "setTagName";
090: public static final String TAG_NAME = "tag-name";
091: public static final String TYPE_CLASS = "type-class";
092: public static final String TYPES = "types";
093:
094: public static final String BASE_CONFIG = "base-config"; //$NON-NLS-1$
095: public static final String TYPE_LOCATION = "type-location"; //$NON-NLS-1$
096: public static final String PREFIX_URI = "http://www.activexml.org/2004/Rules"; //$NON-NLS-1$
097:
098: public static File BASE_CFG_FILE = null;
099:
100: public static long BASE_MOD_TS = -1;
101:
102: public static Element BASE_ROOT = new Element("root");
103:
104: private static ArrayList pluginsList = new ArrayList();
105:
106: private static PluginManager pluginLoader = PluginManager
107: .getInstance(AXCompiler.class.getClassLoader());
108:
109: private static Configuration types = new Configuration("type",
110: new HashMap());
111:
112: private static HashMap rules = new HashMap();
113: private static HashMap ruleMap = new HashMap();
114: private static HashMap rulesTimestamp = new HashMap();
115: private static HashMap datasources = new HashMap();
116:
117: private static List arguments = new ArrayList();
118: private static List instructions = new ArrayList();
119: private static List lexers = new ArrayList();
120:
121: private static AXCompiler compiler = null;
122:
123: private static boolean initializing = false;
124:
125: private static Object invoker = null;
126:
127: private TransformerFactory transformerFactory = null;
128: private Transformer transformer = null;
129:
130: protected AXCompiler(String configPath, Object invoker)
131: throws Exception {
132:
133: this .invoker = invoker;
134:
135: AXCompiler.BASE_CFG_FILE = BASE.getFile(configPath, this
136: .getClass());
137:
138: loadRoot();
139: }
140:
141: public static void addArgument(String value) {
142: synchronized (arguments) {
143: arguments.add(value);
144: }
145: }
146:
147: public static String getArgument(int index) {
148: return (String) arguments.get(index);
149: }
150:
151: protected void init(List inits) throws Exception {
152: int size = inits.size();
153:
154: Element element = null;
155:
156: Configuration config = null;
157:
158: Class cls = null;
159:
160: JDOMXPath xpath = null;
161:
162: AbstractConfig initModule = null;
163:
164: String xpathText = null;
165:
166: for (int i = 0; i < size; i++) {
167: element = (Element) inits.get(i);
168:
169: if (match(element)) {
170: try {
171: if (element.getContentSize() > 0) {
172: this .init(element.getChildren());
173: }
174:
175: xpathText = "//init-type[@id='"
176: + element.getAttributeValue("type")
177: + "']/@class";
178:
179: LoggerWriter.log(xpathText, Level.DEBUG_INT,
180: AXCompiler.class);
181:
182: xpath = new JDOMXPath(xpathText);
183:
184: cls = Class.forName(((Attribute) xpath
185: .selectSingleNode(AXCompiler.BASE_ROOT))
186: .getValue());
187:
188: config = new Configuration("", this
189: .compileProperties(element, null));
190:
191: initModule = (AbstractConfig) (cls
192: .getConstructor(new Class[] { Configuration.class }))
193: .newInstance(new Object[] { config });
194:
195: initModule.init();
196: } catch (Exception ex) {
197: if ("true".equalsIgnoreCase(element
198: .getAttributeValue("required"))) {
199: throw ex;
200: } else {
201: LoggerWriter.log(BASE.getValueFromObject(ex),
202: Level.ERROR_INT, AXCompiler.class);
203: }
204: }
205: }
206: }
207: }
208:
209: protected static void loadRoot() throws Exception {
210: if (AXCompiler.BASE_CFG_FILE == null
211: || (AXCompiler.BASE_CFG_FILE.lastModified() != AXCompiler.BASE_MOD_TS)) {
212:
213: synchronized (AXCompiler.BASE_ROOT) {
214: SAXBuilder builder = new SAXBuilder();
215:
216: Document doc = builder.build(AXCompiler.BASE_CFG_FILE);
217:
218: BASE_ROOT = doc.getRootElement();
219:
220: AXCompiler.BASE_MOD_TS = AXCompiler.BASE_CFG_FILE
221: .lastModified();
222:
223: AXCompiler.expireRules();
224: }
225: }
226: }
227:
228: public static AXCompiler getInstance() {
229: try {
230: loadRoot();
231: } catch (Exception ex) {
232: LoggerWriter.log(BASE.getValueFromObject(ex),
233: Level.DEBUG_INT, AXCompiler.class);
234: }
235:
236: return compiler;
237: }
238:
239: public static AXCompiler getInstance(String typePath, Object invoker)
240: throws Exception {
241:
242: if (compiler == null) {
243: //compiler = new AXCompiler(typePath, invoker);
244:
245: Class cmpClass = Class.forName(System
246: .getProperty("compiler"));
247:
248: compiler = (AXCompiler) cmpClass.getConstructor(
249: new Class[] { String.class, Object.class })
250: .newInstance(new Object[] { typePath, invoker });
251:
252: JDOMXPath xpath = new JDOMXPath(
253: "//compiler-init[@invoker-class='"
254: + invoker.getClass().getName()
255: + "' or not(@invoker-class)]");
256:
257: List list = xpath.selectNodes(AXCompiler.BASE_ROOT);
258:
259: Element compilerInit = null;
260:
261: String regexProp = null;
262:
263: String regEx = null;
264:
265: int size = list.size();
266:
267: for (int i = 0; i < size; i++) {
268: compilerInit = (Element) list.get(i);
269:
270: if (match(compilerInit)) {
271:
272: xpath = new JDOMXPath("init[@invoker-class='"
273: + invoker.getClass().getName()
274: + "' or not(@invoker-class)");
275:
276: compiler.init(xpath.selectNodes(compilerInit));
277: }
278: }
279:
280: compiler.init(xpath.selectNodes(AXCompiler.BASE_ROOT));
281:
282: LoggerWriter
283: .log(
284: "(TM) Business Applications and Services Engine (BASE) has been initialized.",
285: Level.INFO_INT, AXCompiler.class);
286: LoggerWriter
287: .log(
288: "(TM) eXtensible Server-Side Language Interpreter (XSSL) has been initialized.",
289: Level.INFO_INT, AXCompiler.class);
290: }
291:
292: return compiler;
293: }
294:
295: public static boolean match(Element elm) throws Exception {
296: boolean flag = true;
297:
298: if (elm.getAttributeValue("filter-type") == null) {
299: elm = elm.getChild("filter");
300: }
301:
302: if (elm != null) {
303:
304: JDOMXPath xpath = new JDOMXPath("//filter-type[@id='"
305: + elm.getAttributeValue("filter-type")
306: + "']/@class");
307:
308: Attribute attr = (Attribute) xpath
309: .selectSingleNode(AXCompiler.BASE_ROOT);
310:
311: Class cls = Class.forName(attr.getValue());
312:
313: AbstractCompilerFilter filter = (AbstractCompilerFilter) cls
314: .newInstance();
315:
316: flag = filter.filter(elm);
317: } else {
318: flag = true;
319: }
320:
321: return flag;
322: }
323:
324: public HashMap compileProperties(List elements,
325: Configuration template) throws Exception {
326: HashMap map = new HashMap();
327:
328: if (elements != null) {
329: int size = elements.size();
330:
331: LoggerWriter.log(
332: "[ADD PROPERTIES] Property collections count: "
333: + size + " [PROPERTIES ADD]",
334: Level.DEBUG_INT, AXCompiler.class);
335:
336: for (int i = 0; i < size; i++) {
337: map
338: .putAll(compileProperties(elements.get(i),
339: template));
340: }
341: }
342:
343: return map;
344: }
345:
346: public boolean hasExpired(String rulePath, File f) {
347: LoggerWriter.log("[START HAS_EXPIRED] Did resource " + rulePath
348: + " expire? [HAS_EXPIRED START]", Level.DEBUG_INT,
349: AXCompiler.class);
350:
351: boolean flag = false;
352:
353: synchronized (rulesTimestamp) {
354:
355: Long lng = (Long) rulesTimestamp.get(rulePath);
356:
357: LoggerWriter.log("[HAS_EXPIRED] Original timestamp: " + lng
358: + " [HAS_EXPIRED]", Level.DEBUG_INT,
359: AXCompiler.class);
360:
361: long ts = lng != null ? lng.longValue() : -1;
362:
363: LoggerWriter.log(
364: "[HAS_EXPIRED] Original timestamp evaluated: " + ts
365: + " [HAS_EXPIRED]", Level.DEBUG_INT,
366: AXCompiler.class);
367:
368: LoggerWriter.log(
369: "[HAS_EXPIRED] Current resource timestamp: "
370: + f.lastModified() + " [HAS_EXPIRED]",
371: Level.DEBUG_INT, AXCompiler.class);
372:
373: synchronized (rules) {
374:
375: flag = !rules.containsKey(rulePath)
376: || ts != f.lastModified();
377: }
378:
379: LoggerWriter.log("[END HAS_EXPIRED] Resource did "
380: + (!flag ? "not" : "")
381: + " expire. [HAS_EXPIRED END]", Level.DEBUG_INT,
382: AXCompiler.class);
383: }
384:
385: return flag;
386: }
387:
388: public XSSLAction compileRule(IPage page, File f, String rulePath)
389: throws Exception {
390: return compileRule(page, f, rulePath, null);
391: }
392:
393: public abstract HashMap compileProperties(Object elm,
394: Configuration stemplate) throws Exception;
395:
396: public XSSLAction compileRule(IPage page, File f, String rulePath,
397: String qualifierXml) throws Exception {
398: XSSLAction transaction = null;
399:
400: Exception exc = null;
401: if (f.exists()) {
402: XSSLAction original = null;
403:
404: LoggerWriter.log("Finding Transaction Rule: " + rulePath,
405: Level.DEBUG_INT, AXCompiler.class);
406:
407: synchronized (rules) {
408: try {
409: if (rules.containsKey(rulePath)
410: && rules.get(rulePath) == null) {
411: rules.wait();
412: }
413:
414: if ((original = (XSSLAction) rules.get(rulePath)) != null
415: && !hasExpired(rulePath, f)) {
416: LoggerWriter.log("Found non-expired rule: "
417: + rulePath, Level.DEBUG_INT,
418: AXCompiler.class);
419:
420: original = (XSSLAction) rules.get(rulePath);
421: } else {
422:
423: rules.put(rulePath, null);
424:
425: if (original != null) {
426: destroy(original.getThreads());
427: }
428:
429: original = this .compileSource(page, f,
430: rulePath, qualifierXml);
431:
432: if (original != null) {
433: rules.put(rulePath, original);
434:
435: synchronized (ruleMap) {
436:
437: ruleMap.put(page.getName(), original);
438:
439: LoggerWriter.log("Rule " + rulePath
440: + " has been compiled...",
441: Level.DEBUG_INT,
442: AXCompiler.class);
443:
444: synchronized (rulesTimestamp) {
445: rulesTimestamp.put(rulePath,
446: new Long(f.lastModified()));
447: LoggerWriter
448: .log(
449: "Rule "
450: + rulePath
451: + " Compilation Timestamp has been stored as "
452: + f
453: .lastModified(),
454: Level.DEBUG_INT,
455: AXCompiler.class);
456: }
457: }
458: } else {
459: throw new Exception(
460: "Rule did not compile correctly!");
461: }
462:
463: rules.notifyAll();
464: }
465:
466: transaction = (XSSLAction) original.newInstance(
467: null, null);
468:
469: this
470: .prepareTransaction(page, rulePath,
471: transaction);
472:
473: transaction.setTransactionComponent(
474: "xssl-rule-file", f);
475:
476: transaction.setPhysicalPath(f.getPath());
477:
478: Document doc = new Document();
479:
480: doc.setRootElement(transaction);
481: } catch (Exception ex) {
482: rules.remove(rulePath);
483:
484: throw ex;
485: } finally {
486: rules.notifyAll();
487: }
488: }
489: } else {
490: f = null;
491: }
492:
493: return transaction;
494: }
495:
496: public XSSLAction compileSingleSource(IPage page, Object xddSource,
497: String rulePath, String qualifierXml) throws Exception {
498:
499: XSSLAction transaction = this .compileSource(page, xddSource,
500: rulePath, qualifierXml);
501:
502: return this .prepareTransaction(page, rulePath, transaction);
503: }
504:
505: protected XSSLAction prepareTransaction(IPage page,
506: String rulePath, XSSLAction transaction) {
507: if (page != null) {
508:
509: transaction.getPersistance().storeObject("xssl-action",
510: page.getTransactionAction());
511:
512: LoggerWriter.log("Setting transaction controller: "
513: + page.getTransactionController(), Level.DEBUG_INT,
514: AXCompiler.class);
515:
516: transaction.setTransactionComponent("xssl-mapping", page);
517: transaction.setTransactionComponent("xssl-controller", page
518: .getTransactionController());
519: transaction.setTransactionComponent("xssl-request", page
520: .getTransactionRequest());
521: transaction.setTransactionComponent("xssl-response", page
522: .getTransactionResponse());
523: transaction.setTransactionComponent("xssl-config", page
524: .getTransactionConfig());
525: transaction.setTransactionComponent("xssl-session", page
526: .getTransactionSession());
527: transaction.setWorkingDirectory(page.getWorkingDirectory());
528: }
529:
530: transaction.setRulePath(rulePath);
531:
532: return transaction;
533: }
534:
535: protected XSSLAction compileSource(IPage page, Object xddSource,
536: String rulePath, String qualifierXml) throws Exception {
537:
538: LoggerWriter.log("Compiling rule: " + rulePath, Level.INFO_INT,
539: AXCompiler.class);
540:
541: XSSLAction.removeGlobalPersistance(rulePath);
542:
543: Object ruleRoot = this .compileSource(xddSource, rulePath,
544: qualifierXml);
545:
546: XSSLAction original = (XSSLAction) this .getCompiledComponent(
547: page, ruleRoot, null, null, rulePath);
548:
549: original.setConfig(page);
550:
551: original.setOriginalRule(original);
552:
553: return original;
554:
555: }
556:
557: protected abstract Object compileSource(Object xddSource,
558: String rulePath, String qualifierXml) throws Exception;
559:
560: public Object lexDocument(Object document) throws Exception {
561: int size = lexers.size();
562:
563: AbstractLexer lexer = null;
564:
565: for (int i = 0; i < size; i++) {
566: lexer = (AbstractLexer) lexers.get(i);
567:
568: document = lexer.transform(document);
569: }
570:
571: return document;
572: }
573:
574: public XSSLComponent getCompiledComponent(IPage page,
575: Object element, XSSLComponent parent, XSSLAction template,
576: String path) throws Exception {
577: int size = instructions.size();
578:
579: AbstractInstruction instruction = null;
580:
581: AbstractType baseClass = null;
582:
583: XSSLComponent component = null;
584:
585: for (int i = 0; i < size; i++) {
586: instruction = (AbstractInstruction) instructions.get(i);
587:
588: try {
589:
590: baseClass = instruction.match(element);
591: } catch (Exception ex) {
592: LoggerWriter.log(BASE.getValueFromObject(ex),
593: Level.DEBUG_INT, this .getClass());
594: }
595:
596: if (instruction
597: .getBooleanProperty(AbstractInstruction.BREAK)) {
598: break;
599: }
600:
601: if (baseClass != null) {
602:
603: String prefix = instruction.getComponentPrefix(element);
604: String object = instruction.getComponentSuffix(element);
605: String id = instruction.getComponentId(element);
606: HashMap properties = instruction
607: .getComponentProperties(element);
608:
609: component = baseClass.loadComponent(id, properties,
610: element, page, template, parent, path);
611:
612: if (component != null) {
613:
614: if (!"".equals(prefix)
615: && !(component instanceof XContainer)) {
616: LoggerWriter.log(
617: "New instance has been assigned an object refernce id: "
618: + object, Level.DEBUG_INT,
619: AXCompiler.class);
620:
621: component.setProperty(XSSLReturn.REFERENCE_ID,
622: object);
623: }
624:
625: if (parent == null) {
626: parent = (XSSLAction) component;
627: }
628:
629: if (template == null) {
630: template = (XSSLAction) component;
631: }
632:
633: if (id != null && !"".equals(id) && parent != null
634: && template != null) {
635: parent.addIndexedComponent(id, component);
636: template.addIndexedComponent(id, component);
637: }
638:
639: component.setRoot(template);
640: component.setParent(parent);
641: component.setConfig(page);
642:
643: element = null;
644: properties = null;
645: id = null;
646: }
647:
648: AbstractValidator.doValidation(component);
649:
650: break;
651: }
652: }
653:
654: return component;
655: }
656:
657: public boolean hasType(String xmlTag) {
658: return types.hasProperty(xmlTag);
659: }
660:
661: public AbstractType getType(String xmlTag) {
662: return (AbstractType) types.getPropertyAsObject(xmlTag);
663: }
664:
665: public static synchronized void addTag(String id, AbstractType type) {
666: types.addProperty(id, type);
667: }
668:
669: public static Class loadClass(String className) {
670: return pluginLoader.loadClass(className);
671: }
672:
673: public XSSLAction getRule(String id) {
674: return (XSSLAction) ((XSSLAction) rules.get(id)).newInstance(
675: null, null);
676: }
677:
678: public void addDataSource(String id, IDataSource ds) {
679: LoggerWriter.log("Storing intialized datasource: " + id,
680: Level.INFO_INT, this .getClass());
681:
682: synchronized (datasources) {
683:
684: datasources.put(id, ds);
685: }
686:
687: }
688:
689: public static synchronized void destroy(ArrayList threads) {
690: int size = threads.size();
691:
692: XSSLAction thread = null;
693:
694: while (!threads.isEmpty()) {
695: thread = (XSSLAction) threads.remove(0);
696: if (thread.hasExecuted()) {
697: try {
698: ((ITransactionFinalizable) thread).doFinalize();
699: } catch (Exception ex) {
700: LoggerWriter.log(BASE.getValueFromObject(ex),
701: Level.DEBUG_INT, AXCompiler.class);
702: }
703: }
704: }
705: }
706:
707: public static synchronized void expire(String rulePath)
708: throws Exception {
709: File f = BASE.getFile(rulePath, AXCompiler.class);
710:
711: f.setLastModified(System.currentTimeMillis());
712: }
713:
714: public static synchronized void expireRules() throws Exception {
715:
716: Iterator iter = rules.keySet().iterator();
717:
718: while (iter.hasNext()) {
719: expire((String) iter.next());
720: }
721: }
722:
723: public static Configuration getTypes() {
724: return types;
725: }
726:
727: public IDataSource getDataSource(String id) {
728: IDataSource ds = null;
729:
730: synchronized (datasources) {
731: ds = (IDataSource) datasources.get(id);
732: }
733:
734: return ds;
735: }
736:
737: /**
738: * @return
739: */
740: public static PluginManager getPluginManager() {
741: return pluginLoader;
742: }
743:
744: public static Object getInvoker() {
745: return invoker;
746: }
747:
748: public static Class getInvokerClass() {
749: return invoker.getClass();
750: }
751:
752: /**
753: * @param instruction
754: */
755: public static void addInstruction(AbstractInstruction instruction) {
756: instructions.add(instruction);
757: }
758:
759: public static void addLexer(AbstractLexer lexer) {
760: lexers.add(lexer);
761: }
762: }
|