001: package org.drools.brms.server.builder;
002:
003: /*
004: * Copyright 2005 JBoss Inc
005: *
006: * Licensed under the Apache License, Version 2.0 (the "License");
007: * you may not use this file except in compliance with the License.
008: * You may obtain a copy of the License at
009: *
010: * http://www.apache.org/licenses/LICENSE-2.0
011: *
012: * Unless required by applicable law or agreed to in writing, software
013: * distributed under the License is distributed on an "AS IS" BASIS,
014: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
015: * See the License for the specific language governing permissions and
016: * limitations under the License.
017: */
018:
019: import java.io.ByteArrayOutputStream;
020: import java.io.IOException;
021: import java.io.StringReader;
022: import java.util.ArrayList;
023: import java.util.Collections;
024: import java.util.Iterator;
025: import java.util.List;
026: import java.util.Properties;
027: import java.util.jar.JarEntry;
028: import java.util.jar.JarInputStream;
029:
030: import org.drools.brms.client.common.AssetFormats;
031: import org.drools.compiler.PackageBuilder;
032: import org.drools.compiler.PackageBuilderConfiguration;
033: import org.drools.lang.dsl.DSLMappingFile;
034: import org.drools.lang.dsl.DSLMappingParseException;
035: import org.drools.lang.dsl.DefaultExpander;
036: import org.drools.repository.AssetItem;
037: import org.drools.repository.AssetItemIterator;
038: import org.drools.repository.PackageItem;
039: import org.drools.repository.RulesRepositoryException;
040: import org.drools.rule.MapBackedClassLoader;
041: import org.drools.rule.builder.dialect.java.JavaDialectConfiguration;
042: import org.drools.util.ChainedProperties;
043:
044: /**
045: * This decorates the drools-compiler PackageBuilder
046: * with some functionality needed for the BRMS.
047: * This can use the BRMS repo as a classpath.
048: *
049: * @author Michael Neale
050: */
051: public class BRMSPackageBuilder extends PackageBuilder {
052:
053: private List<DSLMappingFile> dslFiles;
054: private DefaultExpander expander;
055:
056: /**
057: * This will give you a fresh new PackageBuilder
058: * using the given classpath.
059: */
060: public static BRMSPackageBuilder getInstance(
061: List<JarInputStream> classpath) {
062: ClassLoader parentClassLoader = Thread.currentThread()
063: .getContextClassLoader();
064: if (parentClassLoader == null) {
065: parentClassLoader = BRMSPackageBuilder.class
066: .getClassLoader();
067: }
068: MapBackedClassLoader loader = new MapBackedClassLoader(
069: parentClassLoader);
070: try {
071: for (JarInputStream jis : classpath) {
072: JarEntry entry = null;
073: byte[] buf = new byte[1024];
074: int len = 0;
075: while ((entry = jis.getNextJarEntry()) != null) {
076: if (!entry.isDirectory()) {
077: ByteArrayOutputStream out = new ByteArrayOutputStream();
078: while ((len = jis.read(buf)) >= 0) {
079: out.write(buf, 0, len);
080: }
081:
082: loader.addResource(entry.getName(), out
083: .toByteArray());
084: }
085: }
086:
087: }
088: } catch (IOException e) {
089: throw new RulesRepositoryException(e);
090: }
091:
092: // See if we can find a packagebuilder.conf
093: // We do this manually here, as we cannot rely on PackageBuilder doing this correctly
094: // note this chainedProperties already checks System properties too
095: ChainedProperties chainedProperties = new ChainedProperties(
096: BRMSPackageBuilder.class.getClassLoader(), // pass this as it searches currentThread anyway
097: "packagebuilder.conf", false); // false means it ignores any default values
098:
099: // the default compiler. This is nominally JANINO but can be overridden by setting drools.dialect.java.compiler to ECLIPSE
100: Properties properties = new Properties();
101: properties.setProperty("drools.dialect.java.compiler",
102: chainedProperties.getProperty(
103: "drools.dialect.java.compiler", "JANINO"));
104: PackageBuilderConfiguration pkgConf = new PackageBuilderConfiguration(
105: properties);
106: pkgConf.setClassLoader(loader);
107:
108: return new BRMSPackageBuilder(pkgConf);
109:
110: }
111:
112: /**
113: * This will return the preferred compiler, according to the System property
114: * drools.compiler (JANINO|ECLIPSE) - default is JANINO due to classpath issues
115: * mainly in tomcat, grrr...
116: */
117: static int getPreferredBRMSCompiler() {
118: if (System
119: .getProperty("drools.dialect.java.compiler", "JANINO")
120: .equals("ECLIPSE")) {
121: return JavaDialectConfiguration.ECLIPSE;
122: } else {
123: return JavaDialectConfiguration.JANINO;
124: }
125: }
126:
127: /**
128: * In the BRMS you should not need to use this, use the getInstance factory method instead.
129: * @param config
130: */
131: public BRMSPackageBuilder(PackageBuilderConfiguration config) {
132: super (config);
133: }
134:
135: /**
136: * This will reset the errors.
137: */
138: public void clearErrors() {
139: super .resetErrors();
140: }
141:
142: public void setDSLFiles(List<DSLMappingFile> files) {
143: this .dslFiles = files;
144: }
145:
146: public List<DSLMappingFile> getDSLMappingFiles() {
147: return Collections.unmodifiableList(this .dslFiles);
148: }
149:
150: /**
151: * Load up all the DSL mappping files for the given package.
152: */
153: public static List<DSLMappingFile> getDSLMappingFiles(
154: PackageItem pkg, DSLErrorEvent err) {
155: List<DSLMappingFile> result = new ArrayList<DSLMappingFile>();
156: AssetItemIterator it = pkg
157: .listAssetsByFormat(new String[] { AssetFormats.DSL });
158: while (it.hasNext()) {
159: AssetItem item = (AssetItem) it.next();
160: String dslData = item.getContent();
161: DSLMappingFile file = new DSLMappingFile();
162: try {
163: if (file.parseAndLoad(new StringReader(dslData))) {
164: result.add(file);
165: } else {
166: List errs = file.getErrors();
167: for (Iterator iter = errs.iterator(); iter
168: .hasNext();) {
169: DSLMappingParseException e = (DSLMappingParseException) iter
170: .next();
171: err.recordError(item, "Line " + e.getLine()
172: + " : " + e.getMessage());
173: }
174: }
175:
176: } catch (IOException e) {
177: throw new RulesRepositoryException(e);
178: }
179:
180: }
181:
182: return result;
183: }
184:
185: /**
186: * Load up all the Jars for the given package.
187: */
188: public static List<JarInputStream> getJars(PackageItem pkg) {
189: List<JarInputStream> result = new ArrayList<JarInputStream>();
190: AssetItemIterator ait = pkg
191: .listAssetsByFormat(new String[] { AssetFormats.MODEL });
192: while (ait.hasNext()) {
193: AssetItem item = (AssetItem) ait.next();
194: if (item.getBinaryContentAttachment() != null) {
195: try {
196: result.add(new JarInputStream(item
197: .getBinaryContentAttachment(), false));
198: } catch (IOException e) {
199: throw new RulesRepositoryException(e);
200: }
201: }
202: }
203: return result;
204: }
205:
206: /**
207: * This is used when loading Jars, DSLs etc to report errors.
208: */
209: public static interface DSLErrorEvent {
210: public void recordError(AssetItem asset, String message);
211: }
212:
213: /**
214: * Returns true if this package uses a DSL.
215: */
216: public boolean hasDSL() {
217: return this .dslFiles != null && this .dslFiles.size() > 0;
218: }
219:
220: /**
221: * Returns an expander for DSLs (only if there is a DSL configured for this package).
222: */
223: public DefaultExpander getDSLExpander() {
224: if (this .expander == null) {
225: expander = new DefaultExpander();
226: for (DSLMappingFile file : this.dslFiles) {
227: expander.addDSLMapping(file.getMapping());
228: }
229: }
230: return expander;
231: }
232:
233: }
|