/** * Copyright 2010 JBoss Inc * * Licensed 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.ode.store; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.StringReader; import java.net.URL; import java.util.ArrayList; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; import javax.xml.namespace.QName; import org.apache.ode.bpel.compiler.api.CompilationException; import org.apache.ode.bpel.dd.DeployDocument; import org.apache.ode.bpel.dd.TDeployment; import org.apache.ode.bpel.iapi.ContextException; import org.apache.ode.bpel.iapi.Endpoint; import org.apache.ode.bpel.iapi.EndpointReference; import org.apache.ode.bpel.iapi.EndpointReferenceContext; import org.apache.ode.bpel.iapi.ProcessConf; import org.apache.ode.bpel.iapi.ProcessState; import org.apache.ode.utils.DOMUtils; import org.drools.builder.ResourceConfiguration; import org.drools.builder.ResourceType; import org.drools.compiler.DroolsParserException; import org.drools.compiler.PackageBuilder; import org.drools.compiler.ResourceTypeBuilder; import org.drools.compiler.RuleFlowLoadError; import org.drools.io.InternalResource; import org.drools.io.Resource; import org.drools.ode.core.BPELProcess; import org.drools.util.StringUtils; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; public class BPELResourceTypeBuilder implements ResourceTypeBuilder { private PackageBuilder packageBuilder; public void addKnowledgeResource(Resource resource, ResourceType type, ResourceConfiguration configuration) { try { generatePackage(); System.out.println("Adding BPEL resource " + resource); URL url = ((InternalResource) resource).getURL(); File file = null; if ( "file".equals( url.getProtocol() ) ) { file = new File( StringUtils.toURI( url.toString() ).getSchemeSpecificPart() ); } else { throw new IllegalArgumentException("ODE BPEL resource is not a file! " + resource); } if ( ((InternalResource) resource).isDirectory() ) { List<BPELProcess> processes = readProcesses(file); for (BPELProcess process: processes) { packageBuilder.getPackage().addProcess(process); } } else { List<BPELProcess> processes = readProcessesFromJar(resource.getInputStream(), file.getName()); byte[] bytes = getBytesFromFile(file); for (BPELProcess process: processes) { process.setBPELJar(bytes); packageBuilder.getPackage().addProcess(process); } } // TODO: handle exceptions // throw new IllegalArgumentException("ODE BPEL resource is not a directory! " + resource); } catch (Exception e) { packageBuilder.getErrors().add(new RuleFlowLoadError("Exception while loading BPEL resource " + resource, e)); } } private void generatePackage() { try { packageBuilder.addPackageFromDrl(new StringReader("package org.drools.ode")); } catch (DroolsParserException e) { // should never occur e.printStackTrace( System.err ); } catch (IOException e) { // should never occur e.printStackTrace( System.err ); } } public static List<BPELProcess> readProcessesFromJar(InputStream input, String name) throws IOException { // unzip file in temp dir ZipInputStream inputStream = new ZipInputStream(input); ZipEntry ze = null; String tmpDirName = System.getProperty("java.io.tmpdir") + File.separator + "Drools_ODE" + File.separator + name + File.separator; File tmpDir = new File(tmpDirName); tmpDir.mkdirs(); List<File> tmpFiles = new ArrayList<File>(); while ((ze = inputStream.getNextEntry()) != null) { String tmpFileName = ze.getName(); int index = tmpFileName.lastIndexOf(File.separator); if (index != -1) { tmpFileName = tmpFileName.substring(index + 1); } File tmpFile = new File(tmpDirName + tmpFileName); tmpFile.createNewFile(); FileOutputStream fout = new FileOutputStream(tmpFile); for (int c = inputStream.read(); c != -1; c = inputStream.read()) { fout.write(c); } inputStream.closeEntry(); fout.close(); tmpFiles.add(tmpFile); } inputStream.close(); // parse processes return readProcesses(tmpDir); } private static List<BPELProcess> readProcesses(File dir) { List<ProcessConf> processes = deploy(dir); List<BPELProcess> result = new ArrayList<BPELProcess>(); for (ProcessConf ODEprocess: processes) { BPELProcess process = new BPELProcess(); process.setId(ODEprocess.getProcessId().toString()); for (Endpoint endpoint: ODEprocess.getProvideEndpoints().values()) { process.setName(endpoint.serviceName.toString()); process.setPackageName(endpoint.serviceName.getNamespaceURI()); } process.setProcessConf(ODEprocess); System.out.println("Adding process " + process.getId()); result.add(process); } return result; } public void setPackageBuilder(PackageBuilder packageBuilder) { this.packageBuilder = packageBuilder; } private static List<ProcessConf> deploy(File deploymentUnitDirectory) { int version = 1; // Create the DU and compile/scan it before acquiring lock. final DeploymentUnitDir du = new DeploymentUnitDir(deploymentUnitDirectory); try { du.compile(); } catch (CompilationException ce) { throw new ContextException("Deployment failed due to compile errors", ce); } du.scan(); final DeployDocument dd = du.getDeploymentDescriptor(); final List<ProcessConf> processes = new ArrayList<ProcessConf>(); for (TDeployment.Process processDD : dd.getDeploy().getProcessList()) { QName pid = toPid(processDD.getName(), version); ProcessConfImpl pconf = new ProcessConfImpl( pid, processDD.getName(), version, du, processDD, new Date(), calcInitialProperties(processDD), ProcessState.ACTIVE, new EndpointReferenceContext() { public EndpointReference resolveEndpointReference(Element element) { return null; } public EndpointReference convertEndpoint(QName qName, Element element) { return null; } @SuppressWarnings("unchecked") public Map getConfigLookup(EndpointReference epr) { return Collections.EMPTY_MAP; } } ); processes.add(pconf); } return processes; } public static Map<QName, Node> calcInitialProperties(TDeployment.Process dd) { HashMap<QName, Node> ret = new HashMap<QName, Node>(); if (dd.getPropertyList().size() > 0) { for (TDeployment.Process.Property property : dd.getPropertyList()) { Element elmtContent = DOMUtils.getElementContent(property.getDomNode()); if (elmtContent != null) { // We'll need DOM Level 3 Document doc = DOMUtils.newDocument(); doc.appendChild(doc.importNode(elmtContent, true)); ret.put(property.getName(), doc.getDocumentElement()); } else ret.put(property.getName(), property.getDomNode().getFirstChild()); } } return ret; } private static QName toPid(QName processType, long version) { return new QName(processType.getNamespaceURI(), processType.getLocalPart() + "-" + version); } public static byte[] getBytesFromFile(File file) throws IOException { InputStream is = new FileInputStream(file); long length = file.length(); byte[] bytes = new byte[(int)length]; int offset = 0; int numRead = 0; while (offset < bytes.length && (numRead=is.read(bytes, offset, bytes.length-offset)) >= 0) { offset += numRead; } is.close(); return bytes; } }