001/*
002 * (C) Copyright 2006-2010 Nuxeo SA (http://nuxeo.com/) and others.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *     http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 *
016 * Contributors:
017 *     bstefanescu
018 */
019package org.nuxeo.runtime.model.impl;
020
021import java.io.BufferedWriter;
022import java.io.File;
023import java.io.FileWriter;
024import java.io.IOException;
025import java.io.OutputStream;
026import java.io.OutputStreamWriter;
027import java.io.StringWriter;
028import java.io.Writer;
029import java.net.URL;
030
031import javax.xml.parsers.DocumentBuilderFactory;
032import javax.xml.parsers.ParserConfigurationException;
033
034import org.apache.commons.logging.Log;
035import org.apache.commons.logging.LogFactory;
036import org.apache.xml.serialize.Method;
037import org.apache.xml.serialize.OutputFormat;
038import org.apache.xml.serialize.XMLSerializer;
039import org.nuxeo.runtime.Version;
040import org.nuxeo.runtime.api.Framework;
041import org.nuxeo.runtime.model.ComponentName;
042import org.nuxeo.runtime.model.ExtensionPoint;
043import org.nuxeo.runtime.model.RegistrationInfo;
044import org.w3c.dom.Document;
045import org.w3c.dom.Element;
046
047/**
048 * @author <a href="mailto:bs@nuxeo.com">Bogdan Stefanescu</a>
049 */
050// use by reflection from DevFrameworkBootstrap
051public class ComponentRegistrySerializer {
052
053    private final static Log log = LogFactory.getLog(ComponentRegistrySerializer.class);
054
055    public static void writeIndex(File file) throws IOException {
056        BufferedWriter writer = new BufferedWriter(new FileWriter(file));
057        try {
058            writeIndex(writer);
059        } finally {
060            writer.close();
061        }
062    }
063
064    public static void writeIndex(Writer writer) throws IOException {
065        ComponentManagerImpl mgr = (ComponentManagerImpl) Framework.getRuntime().getComponentManager();
066        for (RegistrationInfo ri : mgr.getRegistrations()) {
067            ComponentName name = ri.getName();
068            if (name == null) {
069                log.error("BUG: Found component with null name");
070                continue;
071            }
072            String src = getComponentSrc(ri);
073            if (src == null) {
074                src = "";
075            }
076
077            String bundle = ri.getBundle();
078            if (bundle == null) {
079                bundle = ri.getContext().getBundle().getSymbolicName();
080            }
081            if (bundle == null) {
082                bundle = "";
083            }
084
085            String cname = name.getName();
086            writer.write("c:");
087            writer.write(cname);
088            writer.write(":");
089            writer.write(bundle);
090            writer.write(":");
091            writer.write(src);
092            writer.write("\n");
093
094            // write services
095            String[] services = ri.getProvidedServiceNames();
096            if (services != null && services.length > 0) {
097                for (String service : services) {
098                    writer.write("s:");
099                    writer.write(cname);
100                    writer.write(":");
101                    writer.write(service);
102                    writer.write("\n");
103                }
104            }
105
106            // write services
107            ExtensionPoint[] xpoints = ri.getExtensionPoints();
108            if (xpoints != null && xpoints.length > 0) {
109                for (ExtensionPoint xpoint : xpoints) {
110                    writer.write("x:");
111                    writer.write(cname);
112                    writer.write(":");
113                    writer.write(xpoint.getName());
114                    writer.write("\n");
115                }
116            }
117        }
118    }
119
120    private static String getComponentSrc(RegistrationInfo ri) {
121        URL url = ri.getXmlFileUrl();
122        if (url != null) {
123            String src;
124            String path = url.toExternalForm();
125            int i = path.lastIndexOf('!');
126            if (i > 0) {
127                String jar = path.substring(0, i);
128                path = path.substring(i + 1);
129                int s = jar.lastIndexOf('/');
130                if (s > -1) {
131                    jar = jar.substring(s + 1);
132                }
133                src = jar + "!" + path;
134            } else {
135                int s = path.lastIndexOf('/');
136                if (s != -1) {
137                    src = path.substring(s + 1);
138                } else {
139                    src = path;
140                }
141            }
142            return src;
143        }
144        return null;
145    }
146
147    public static Document toDocument() {
148        ComponentManagerImpl mgr = (ComponentManagerImpl) Framework.getRuntime().getComponentManager();
149        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
150        Document doc;
151        try {
152            doc = factory.newDocumentBuilder().newDocument();
153        } catch (ParserConfigurationException e) {
154            throw new RuntimeException(e);
155        }
156        Element root = doc.createElement("components");
157        doc.appendChild(root);
158
159        for (RegistrationInfo ri : mgr.getRegistrations()) {
160            ComponentName name = ri.getName();
161            if (name == null) {
162                log.error("BUG: Found component with null name");
163                continue;
164            }
165
166            Element comp = doc.createElement("component");
167            comp.setAttribute("name", name.getName());
168            String impl = ri.getImplementation();
169            if (impl != null && impl.length() > 0) {
170                comp.setAttribute("class", impl);
171            }
172            String bundle = ri.getBundle();
173            if (bundle == null) {
174                bundle = ri.getContext().getBundle().getSymbolicName();
175            }
176            if (bundle != null) {
177                comp.setAttribute("bundle", bundle);
178            }
179            Version v = ri.getVersion();
180            if (v != null) {
181                comp.setAttribute("version", v.toString());
182            }
183            root.appendChild(comp);
184
185            // write source if known
186            String src = getComponentSrc(ri);
187            if (src != null) {
188                comp.setAttribute("src", src);
189            }
190
191            // write documentation
192            String docText = ri.getDocumentation();
193            if (docText != null) {
194                docText = docText.trim();
195                Element docu = doc.createElement("documentation");
196                docu.setTextContent(docText);
197                comp.appendChild(docu);
198            }
199
200            // write services
201            String[] services = ri.getProvidedServiceNames();
202            if (services != null && services.length > 0) {
203                Element svcsEl = doc.createElement("services");
204                for (String service : services) {
205                    Element svcEl = doc.createElement("service");
206                    svcEl.setAttribute("class", service);
207                    svcsEl.appendChild(svcEl);
208                }
209                comp.appendChild(svcsEl);
210            }
211
212            // write extension points
213            ExtensionPoint[] xps = ri.getExtensionPoints();
214            if (xps != null && xps.length > 0) {
215                Element xpsEl = doc.createElement("extension-points");
216                for (ExtensionPoint xp : xps) {
217                    Element xpEl = doc.createElement("extension-point");
218                    xpEl.setAttribute("name", xp.getName());
219                    docText = xp.getDocumentation();
220                    if (docText != null) {
221                        xpEl.setTextContent(docText.trim());
222                    }
223                    xpsEl.appendChild(xpEl);
224                }
225                comp.appendChild(xpsEl);
226            }
227        }
228        return doc;
229    }
230
231    public static void toXML(OutputStream out) throws IOException {
232        toXML(out, "UTF-8");
233    }
234
235    public static void toXML(OutputStream out, String encoding) throws IOException {
236        OutputStreamWriter writer = new OutputStreamWriter(out, encoding);
237        toXML(writer, encoding);
238    }
239
240    public static void toXML(Writer out) throws IOException {
241        toXML(out, "UTF-8");
242    }
243
244    public static void toXML(Writer out, String encoding) throws IOException {
245        Document doc = toDocument();
246        OutputFormat format = new OutputFormat(Method.XML, encoding, true);
247        format.setIndent(2);
248        XMLSerializer serializer = new XMLSerializer(out, format);
249        serializer.serialize(doc);
250        out.flush();
251    }
252
253    public static String toXML() throws IOException {
254        StringWriter writer = new StringWriter();
255        toXML(writer);
256        return writer.toString();
257    }
258
259}