package org.talend.esb.policy.transformation.util.xslt; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.util.Collection; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamReader; import javax.xml.transform.Source; import javax.xml.transform.Templates; import javax.xml.transform.TransformerConfigurationException; import javax.xml.transform.TransformerFactory; import javax.xml.transform.URIResolver; import javax.xml.transform.dom.DOMSource; import javax.xml.transform.stream.StreamSource; import org.apache.cxf.common.classloader.ClassLoaderUtils; import org.apache.cxf.helpers.IOUtils; import org.apache.cxf.interceptor.Fault; import org.apache.cxf.io.CachedOutputStream; import org.apache.cxf.message.Message; import org.apache.cxf.message.MessageUtils; import org.talend.esb.policy.transformation.TransformationAssertion; import org.talend.esb.policy.transformation.TransformationPolicyBuilder; import org.apache.cxf.staxutils.StaxUtils; import org.apache.cxf.ws.policy.AssertionInfo; import org.apache.cxf.ws.policy.AssertionInfoMap; import org.w3c.dom.Document; public abstract class AbstractXSLTUtil { private String contextPropertyName; private final Templates xsltTemplate; public AbstractXSLTUtil(String xsltPath) { //loading XSLT resource from specified path InputStream xsltStream = null; String absoluteSchemaPath = null; try { CachedOutputStream cos = new CachedOutputStream(); absoluteSchemaPath = loadResource(xsltPath, cos); xsltStream = cos.getInputStream(); if (xsltStream == null) { throw new IllegalArgumentException("Cannot load XSLT from path: " + xsltPath); } }catch(Exception ex){ throw new IllegalArgumentException("Cannot load XSLT from path: " + xsltPath, ex); } TransformerFactory factory = TransformerFactory.newInstance(); factory.setURIResolver(new XSLTResourceResolver(absoluteSchemaPath, xsltPath)); try{ Document doc = StaxUtils.read(xsltStream); xsltTemplate = factory.newTemplates(new DOMSource(doc)); } catch (TransformerConfigurationException e) { throw new IllegalArgumentException( String.format("Cannot create XSLT template from path: %s, error: ", xsltPath, e.getException()), e); } catch (XMLStreamException e) { throw new IllegalArgumentException( String.format("Cannot create XSLT template from path: %s, error: ", xsltPath, e.getNestedException()), e); } finally { if (xsltStream != null) { try { xsltStream.close(); } catch (Exception e) {} } } } class XSLTResourceResolver implements URIResolver { String parentXSLTAbsolutePath = null; String parentXSLTProvidedPath = null; public XSLTResourceResolver(String parentXSLTAbsolutePath, String parentXSLTProvidedPath){ this.parentXSLTAbsolutePath = parentXSLTAbsolutePath; this.parentXSLTProvidedPath = parentXSLTProvidedPath; } public Source resolve(String systemId, String baseURI) { boolean isRemoteLocation = (systemId != null && (systemId.startsWith("http://") || systemId.startsWith("https://"))); //Try to find path to parent XSLT directory String parentXSLTDir = ""; if(parentXSLTAbsolutePath!=null && !isRemoteLocation){ File file = new File(parentXSLTAbsolutePath); if(file.exists()){ parentXSLTDir = file.getParentFile().getAbsolutePath(); } } // Try to resolve path to imported XSLT // using provided resource properties String resURL = null; if (systemId != null) { String XSLTLocation = ""; if (baseURI != null) { XSLTLocation = baseURI.substring(0, baseURI.lastIndexOf("/") + 1); } if (!isRemoteLocation) { resURL = XSLTLocation + systemId; } else { resURL = systemId; } } CachedOutputStream cache = new CachedOutputStream(); InputStream resourceStream = null; String actualXSLTURL = null; try{ // Try to load XSLT using absolute path actualXSLTURL = resURL; loadResource(actualXSLTURL, cache); if(cache.size()==0 && parentXSLTDir!=null && !parentXSLTDir.isEmpty() && !isRemoteLocation){ // XSLT is not found // Try to load XSLT using path to basic XSLT directory // (which is referenced in policy) as root actualXSLTURL = parentXSLTDir+File.separator + resURL; loadResource(actualXSLTURL, cache); } resourceStream = cache.getInputStream(); }catch (IOException ex){ return null; } if (cache.size() != 0) { StreamSource source = new StreamSource(resourceStream); source.setSystemId(actualXSLTURL); return source; }else{ StringBuilder message = new StringBuilder(); message.append("Transformation: can not load internal XSLT with path {"); if(systemId==null){ message.append(resURL); }else{ message.append(systemId); } message.append("}"); throw new RuntimeException(message.toString()); } } } @SuppressWarnings("resource") private String loadResource(String path, OutputStream output) throws IOException{ InputStream resource = null; String absolutePath = null; // try to load resource from file system try { resource = new FileInputStream(path); if(resource!=null){ absolutePath = path; } } catch (FileNotFoundException e) { resource = null; } if (resource == null) { // try to load resource from class loader root resource = ClassLoaderUtils.getResourceAsStream(path, this.getClass()); if(resource!=null){ URL url = ClassLoaderUtils.getResource(path, this.getClass()); if(url!= null){ absolutePath = url.getPath(); } } } if (resource == null) { // try to load schema as web resource try { URL url = new URL(path); resource = url.openStream(); } catch (Exception e) { } } if(resource!=null){ IOUtils.copyAndCloseInput(resource, output); return absolutePath; } return null; } public void handleMessage(Message message) { try { performTransformation(message); confirmPolicyProcessing(message); }catch (RuntimeException e) { throw e; }catch (Exception e) { throw new Fault(e); } } abstract protected void performTransformation(Message message); private void confirmPolicyProcessing(Message message) { AssertionInfoMap aim = message.get(AssertionInfoMap.class); if (aim != null) { Collection<AssertionInfo> ais = aim .get(TransformationPolicyBuilder.TRANSFORMATION); if (ais != null) { for (AssertionInfo ai : ais) { if (ai.getAssertion() instanceof TransformationAssertion) { ai.setAsserted(true); } } } } } public void setContextPropertyName(String propertyName) { contextPropertyName = propertyName; } protected boolean checkContextProperty(Message message) { return contextPropertyName != null && !MessageUtils.getContextualBoolean(message, contextPropertyName, false); } protected Templates getXSLTTemplate() { return xsltTemplate; } protected boolean isRequestor(Message message) { return MessageUtils.isRequestor(message); } protected boolean isGET(Message message) { String method = (String)message.get(Message.HTTP_REQUEST_METHOD); return "GET".equals(method) && message.getContent(XMLStreamReader.class) == null; } }